-- Runs AFTER GoTrue and Storage auto-migrate their schemas.
-- Seeds the admin user (from psql vars :admin_email / :admin_password),
-- the vehicle-photos storage bucket, and storage RLS policies. Idempotent.
--
-- IMPORTANT: the seeded password is a BOOTSTRAP value only. The admin UI
-- enforces a password rotation on first login via
-- auth.users.raw_user_meta_data.must_change_password=true, so the real
-- operational password is NEVER equal to the .env seed.

-- Publish psql vars as GUCs so the DO block can read them reliably.
select set_config('mccars.admin_email',    :'admin_email',    false);
select set_config('mccars.admin_password', :'admin_password', false);

do $$
declare
    v_user_id uuid;
    v_email   text := coalesce(nullif(current_setting('mccars.admin_email', true), ''), 'admin@mccars.local');
    v_pass    text := coalesce(nullif(current_setting('mccars.admin_password', true), ''), 'mc-cars-admin');
begin
    if not exists (select 1 from auth.users where email = v_email) then
        v_user_id := gen_random_uuid();
        insert into auth.users (
            id, instance_id, aud, role, email, encrypted_password,
            email_confirmed_at, raw_app_meta_data, raw_user_meta_data,
            created_at, updated_at, is_super_admin,
            confirmation_token, email_change, email_change_token_new, recovery_token
        ) values (
            v_user_id,
            '00000000-0000-0000-0000-000000000000',
            'authenticated', 'authenticated',
            v_email,
            crypt(v_pass, gen_salt('bf')),
            now(),
            jsonb_build_object('provider','email','providers',jsonb_build_array('email')),
            jsonb_build_object('must_change_password', true),
            now(), now(), false, '', '', '', ''
        );

        insert into auth.identities (
            id, user_id, identity_data, provider, provider_id,
            last_sign_in_at, created_at, updated_at
        ) values (
            gen_random_uuid(), v_user_id,
            jsonb_build_object('sub', v_user_id::text, 'email', v_email),
            'email', v_email,
            now(), now(), now()
        );
    end if;
end
$$;

-- -----------------------------------------------------------------------------
-- Storage bucket + RLS
-- -----------------------------------------------------------------------------
insert into storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
values ('vehicle-photos','vehicle-photos', true, 52428800,
        array['image/jpeg','image/png','image/webp','image/avif'])
on conflict (id) do update
    set public             = excluded.public,
        file_size_limit    = excluded.file_size_limit,
        allowed_mime_types = excluded.allowed_mime_types;

-- Let storage_admin assume app roles for RLS evaluation (idempotent).
grant anon, authenticated, service_role to supabase_storage_admin;

grant select on storage.buckets to anon, authenticated;
grant all on storage.buckets to service_role;
grant select on storage.objects to anon;
grant insert on storage.objects to anon;
grant update on storage.objects to anon;
grant select, insert, update, delete on storage.objects to authenticated;
grant all on storage.objects to service_role;

drop policy if exists "vehicle_photos_public_read"  on storage.objects;
drop policy if exists "vehicle_photos_admin_insert" on storage.objects;
drop policy if exists "vehicle_photos_admin_update" on storage.objects;
drop policy if exists "vehicle_photos_admin_delete" on storage.objects;

create policy "vehicle_photos_public_read"
    on storage.objects for select using (bucket_id = 'vehicle-photos');

create policy "vehicle_photos_admin_insert"
    on storage.objects for insert to authenticated
    with check (bucket_id = 'vehicle-photos');

create policy "vehicle_photos_admin_update"
    on storage.objects for update to authenticated
    using (bucket_id = 'vehicle-photos') with check (bucket_id = 'vehicle-photos');

create policy "vehicle_photos_admin_delete"
    on storage.objects for delete to authenticated
    using (bucket_id = 'vehicle-photos');

-- -----------------------------------------------------------------------------
-- Private bucket for booking documents (ID, payslip)
-- -----------------------------------------------------------------------------
insert into storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
values ('customer-documents','customer-documents', false, 10485760,
        array['image/jpeg','image/png','application/pdf'])
on conflict (id) do update
    set public             = excluded.public,
        file_size_limit    = excluded.file_size_limit,
        allowed_mime_types = excluded.allowed_mime_types;

drop policy if exists "custdocs_anon_upload"    on storage.objects;
drop policy if exists "custdocs_anon_select"    on storage.objects;
drop policy if exists "custdocs_anon_update"    on storage.objects;
drop policy if exists "custdocs_anon_upsert_update" on storage.objects;
drop policy if exists "custdocs_public_upload" on storage.objects;
drop policy if exists "custdocs_public_upsert_update" on storage.objects;
drop policy if exists "custdocs_admin_read"     on storage.objects;
drop policy if exists "custdocs_admin_delete"   on storage.objects;

-- Anon can upload (insert) during booking flow
create policy "custdocs_anon_upload"
    on storage.objects for insert to anon
    with check (bucket_id = 'customer-documents');

-- Anon needs SELECT + UPDATE for x-upsert to work (Supabase storage requirement)
create policy "custdocs_anon_select"
    on storage.objects for select to anon
    using (bucket_id = 'customer-documents');

create policy "custdocs_anon_update"
    on storage.objects for update to anon
    using (bucket_id = 'customer-documents')
    with check (bucket_id = 'customer-documents');

-- Authenticated admins can read/delete
create policy "custdocs_admin_read"
    on storage.objects for select to authenticated
    using (bucket_id = 'customer-documents');

create policy "custdocs_admin_delete"
    on storage.objects for delete to authenticated
    using (bucket_id = 'customer-documents');
