-- Ensure storage objects for all artefacts are removed when a file is deleted
-- by deleting the entire "cabinet_id/file_id" directory prefix in Storage.

-- Helper to delete all objects under a prefix
create or replace function public._delete_storage_prefix(p_bucket text, p_prefix text)
returns void
language plpgsql security definer
set search_path to 'public', 'storage'
as $$
begin
  if p_bucket is null or p_prefix is null then
    return;
  end if;
  -- Delete any objects whose name starts with the prefix + '/'
  delete from storage.objects where bucket_id = p_bucket and name like p_prefix || '/%';
  -- In case an object exists exactly at the prefix (rare but safe)
  delete from storage.objects where bucket_id = p_bucket and name = p_prefix;
end
$$;

-- Update file-level GC to also delete the parent directory prefix (cabinet_id/file_id)
create or replace function public._storage_gc_sql()
returns trigger
language plpgsql security definer
set search_path to 'public', 'storage'
as $$
declare
  v_prefix text;
begin
  -- Derive directory prefix from the file path by removing the last segment (filename)
  -- Example: 'cabinet_id/file_id/filename.ext' -> 'cabinet_id/file_id'
  v_prefix := regexp_replace(old.path, '/[^/]+$', '');

  if tg_op = 'DELETE' then
    -- Delete the original object and any artefacts under the file's directory
    perform public._delete_storage_objects(old.bucket, old.path);
    perform public._delete_storage_prefix(old.bucket, v_prefix);
  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);
      perform public._delete_storage_prefix(old.bucket, v_prefix);
    end if;
  end if;
  return null;
end
$$;


