-- =============================================================================
-- MC Cars - CRM schema: leads + customers + realtime publication.
-- Runs from post-init AFTER auth/storage schemas exist.
-- Idempotent.
-- =============================================================================

-- -----------------------------------------------------------------------------
-- LEADS: landing-page form submissions (anon may INSERT, only authenticated
-- may SELECT/UPDATE).
-- -----------------------------------------------------------------------------
create table if not exists public.leads (
    id               uuid primary key default gen_random_uuid(),
    name             text        not null,
    email            text        not null,
    phone            text        not null default '',
    vehicle_id       uuid        references public.vehicles(id) on delete set null,
    vehicle_label    text        not null default '',  -- denormalized (brand + model) at submit time
    date_from        date,
    date_to          date,
    message          text        not null default '',
    status           text        not null default 'new'
                     check (status in ('new','qualified','disqualified')),
    is_active        boolean     not null default true,    -- false once qualified/disqualified
    admin_notes      text        not null default '',
    source           text        not null default 'website',
    created_at       timestamptz not null default now(),
    updated_at       timestamptz not null default now(),
    qualified_at     timestamptz,
    qualified_by     uuid        references auth.users(id) on delete set null
);

create index if not exists leads_active_created_idx   on public.leads (is_active, created_at desc);
create index if not exists leads_status_idx           on public.leads (status);
create index if not exists leads_vehicle_idx          on public.leads (vehicle_id);

drop trigger if exists leads_touch on public.leads;
create trigger leads_touch
    before update on public.leads
    for each row execute function public.tg_touch_updated_at();

alter table public.leads enable row level security;

drop policy if exists "leads_anon_insert"       on public.leads;
drop policy if exists "leads_admin_select_all"  on public.leads;
drop policy if exists "leads_admin_update"      on public.leads;
drop policy if exists "leads_admin_delete"      on public.leads;

-- Anonymous visitors may submit the booking form, but NOT read anything back.
create policy "leads_anon_insert"
    on public.leads for insert to anon
    with check (true);

create policy "leads_admin_select_all"
    on public.leads for select to authenticated
    using (true);

create policy "leads_admin_update"
    on public.leads for update to authenticated
    using (true) with check (true);

create policy "leads_admin_delete"
    on public.leads for delete to authenticated
    using (true);

grant insert on public.leads to anon;
grant select, insert, update, delete on public.leads to authenticated;
grant all on public.leads to service_role;


-- -----------------------------------------------------------------------------
-- CUSTOMERS: created ONLY by qualifying a lead from the admin panel.
-- Keeps a hard FK back to the originating lead for audit.
-- -----------------------------------------------------------------------------
create table if not exists public.customers (
    id                 uuid primary key default gen_random_uuid(),
    lead_id            uuid not null references public.leads(id) on delete restrict,
    name               text not null,
    email              text not null,
    phone              text not null default '',
    first_contacted_at timestamptz not null default now(),
    notes              text not null default '',
    status             text not null default 'active'
                       check (status in ('active','inactive')),
    created_at         timestamptz not null default now(),
    updated_at         timestamptz not null default now(),
    created_by         uuid references auth.users(id) on delete set null
);

create unique index if not exists customers_lead_unique on public.customers (lead_id);
create index if not exists customers_email_idx on public.customers (email);

drop trigger if exists customers_touch on public.customers;
create trigger customers_touch
    before update on public.customers
    for each row execute function public.tg_touch_updated_at();

alter table public.customers enable row level security;

drop policy if exists "customers_admin_select" on public.customers;
drop policy if exists "customers_admin_insert" on public.customers;
drop policy if exists "customers_admin_update" on public.customers;
drop policy if exists "customers_admin_delete" on public.customers;

create policy "customers_admin_select"
    on public.customers for select to authenticated using (true);

create policy "customers_admin_insert"
    on public.customers for insert to authenticated with check (true);

create policy "customers_admin_update"
    on public.customers for update to authenticated using (true) with check (true);

create policy "customers_admin_delete"
    on public.customers for delete to authenticated using (true);

grant select, insert, update, delete on public.customers to authenticated;
grant all on public.customers to service_role;


-- -----------------------------------------------------------------------------
-- qualify_lead(lead_id, notes)
--   Transactional: marks the lead qualified+inactive and creates the matching
--   customer row. Called via PostgREST RPC by the admin UI.
-- -----------------------------------------------------------------------------
create or replace function public.qualify_lead(p_lead_id uuid, p_notes text default '')
returns public.customers
language plpgsql
security invoker
as $$
declare
    v_lead public.leads;
    v_customer public.customers;
    v_user uuid := auth.uid();
begin
    select * into v_lead from public.leads where id = p_lead_id for update;
    if not found then
        raise exception 'lead % not found', p_lead_id;
    end if;

    if v_lead.status = 'qualified' then
        select * into v_customer from public.customers where lead_id = v_lead.id;
        return v_customer;
    end if;

    update public.leads
       set status       = 'qualified',
           is_active    = false,
           qualified_at = now(),
           qualified_by = v_user,
           admin_notes  = coalesce(nullif(p_notes, ''), admin_notes)
     where id = v_lead.id;

    insert into public.customers (lead_id, name, email, phone, notes, created_by)
    values (v_lead.id, v_lead.name, v_lead.email, v_lead.phone, coalesce(p_notes,''), v_user)
    returning * into v_customer;

    return v_customer;
end;
$$;

revoke all on function public.qualify_lead(uuid, text) from public;
grant execute on function public.qualify_lead(uuid, text) to authenticated;


-- -----------------------------------------------------------------------------
-- disqualify_lead(lead_id, notes)
-- -----------------------------------------------------------------------------
create or replace function public.disqualify_lead(p_lead_id uuid, p_notes text default '')
returns public.leads
language plpgsql
security invoker
as $$
declare
    v_lead public.leads;
begin
    update public.leads
       set status      = 'disqualified',
           is_active   = false,
           admin_notes = coalesce(nullif(p_notes, ''), admin_notes)
     where id = p_lead_id
    returning * into v_lead;

    if not found then
        raise exception 'lead % not found', p_lead_id;
    end if;

    return v_lead;
end;
$$;

revoke all on function public.disqualify_lead(uuid, text) from public;
grant execute on function public.disqualify_lead(uuid, text) to authenticated;


-- -----------------------------------------------------------------------------
-- reopen_lead(lead_id): moves a lead back to active/new (admin correction).
-- -----------------------------------------------------------------------------
create or replace function public.reopen_lead(p_lead_id uuid)
returns public.leads
language plpgsql
security invoker
as $$
declare
    v_lead public.leads;
begin
    update public.leads
       set status       = 'new',
           is_active    = true,
           qualified_at = null,
           qualified_by = null
     where id = p_lead_id
    returning * into v_lead;

    -- If a customer was spawned from this lead, remove it.
    delete from public.customers where lead_id = p_lead_id;

    return v_lead;
end;
$$;

revoke all on function public.reopen_lead(uuid) from public;
grant execute on function public.reopen_lead(uuid) to authenticated;


-- -----------------------------------------------------------------------------
-- Realtime: publish leads + customers so the admin UI sees live inserts/updates.
-- -----------------------------------------------------------------------------
do $$
declare t text;
begin
    if not exists (select 1 from pg_publication where pubname = 'supabase_realtime') then
        create publication supabase_realtime;
    end if;

    foreach t in array array['leads','customers','vehicles'] loop
        if not exists (
            select 1 from pg_publication_tables
             where pubname='supabase_realtime' and schemaname='public' and tablename=t
        ) then
            execute format('alter publication supabase_realtime add table public.%I', t);
        end if;
    end loop;
end
$$;

alter table public.leads     replica identity full;
alter table public.customers replica identity full;
alter table public.vehicles  replica identity full;

-- Tell PostgREST to reload its schema cache after new tables/functions appear.
notify pgrst, 'reload schema';

