-- Files table augments and storage GC hooks

-- 1) Add columns to files if missing
do $$
begin
    if not exists (
        select 1 from information_schema.columns
        where table_schema='public' and table_name='files' and column_name='uploaded_by'
    ) then
        alter table public.files add column uploaded_by uuid references public.profiles(id);
    end if;
    if not exists (
        select 1 from information_schema.columns
        where table_schema='public' and table_name='files' and column_name='size_bytes'
    ) then
        alter table public.files add column size_bytes bigint;
    end if;
    if not exists (
        select 1 from information_schema.columns
        where table_schema='public' and table_name='files' and column_name='source'
    ) then
        alter table public.files add column source text default 'uploader-web';
    end if;
end $$;

-- 2) Unique index for cabinet/path combo
create unique index if not exists uq_files_cabinet_path on public.files(cabinet_id, path);

-- 3) Storage GC helpers (ported from neoFS with storage schema)
create or replace function public._delete_storage_objects(p_bucket text, p_path text)
returns void
language plpgsql security definer
set search_path to 'public', 'storage'
as $$
begin
  if p_bucket is null or p_path is null then
    return;
  end if;
  delete from storage.objects where bucket_id = p_bucket and name = p_path;
  delete from storage.objects where bucket_id = p_bucket and name like p_path || '/%';
end
$$;

create or replace function public._storage_gc_sql()
returns trigger
language plpgsql security definer
set search_path to 'public', 'storage'
as $$
begin
  if tg_op = 'DELETE' then
    perform public._delete_storage_objects(old.bucket, old.path);
  elsif tg_op = 'UPDATE' then
    if (old.bucket is distinct from new.bucket) or (old.path is distinct from new.path) then
      perform public._delete_storage_objects(old.bucket, old.path);
    end if;
  end if;
  return null;
end
$$;

-- 4) Attach GC trigger to files bucket/path changes
drop trigger if exists trg_files_gc on public.files;
create trigger trg_files_gc
after delete or update of bucket, path on public.files
for each row execute function public._storage_gc_sql();

-- 5) Document artefacts GC: remove artefact objects from storage when rows change/delete
create or replace function public._artefact_gc_sql()
returns trigger
language plpgsql security definer
set search_path to 'public', 'storage'
as $$
declare
  v_bucket text;
begin
  if tg_op = 'DELETE' then
    select f.bucket into v_bucket from public.files f where f.id = old.file_id;
    perform public._delete_storage_objects(v_bucket, old.rel_path);
    return old;
  elsif tg_op = 'UPDATE' then
    if (old.rel_path is distinct from new.rel_path) or (old.file_id is distinct from new.file_id) then
      select f.bucket into v_bucket from public.files f where f.id = old.file_id;
      perform public._delete_storage_objects(v_bucket, old.rel_path);
    end if;
    return new;
  end if;
end
$$;

drop trigger if exists trg_document_artefacts_gc on public.document_artefacts;
create trigger trg_document_artefacts_gc
before delete or update of file_id, rel_path on public.document_artefacts
for each row execute function public._artefact_gc_sql();


