-- MDB-Turbo : cœur métier dossiers + checklist visite + base investisseurs
-- Exécuter après création du projet Supabase (auth.users existe déjà).

-- ---------------------------------------------------------------------------
-- Profil utilisateur (lien auth)
-- ---------------------------------------------------------------------------
create table if not exists public.profiles (
  id uuid primary key references auth.users (id) on delete cascade,
  full_name text,
  company_name text,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

-- ---------------------------------------------------------------------------
-- Dossier = opportunité / deal en cours
-- ---------------------------------------------------------------------------
create type public.dossier_status as enum (
  'draft',
  'sourcing',
  'analysis',
  'visit',
  'offer',
  'under_promise',
  'resale',
  'closed_won',
  'closed_lost'
);

create table if not exists public.dossiers (
  id uuid primary key default gen_random_uuid(),
  user_id uuid not null references auth.users (id) on delete cascade,
  title text not null default 'Nouveau dossier',
  status public.dossier_status not null default 'draft',

  -- Localisation
  address_line text,
  city text,
  postal_code text,
  insee_code text,
  latitude double precision,
  longitude double precision,

  -- Physique
  surface_m2 numeric(12, 2),
  land_surface_m2 numeric(12, 2),
  rooms_count smallint,
  dpe_class text check (dpe_class is null or dpe_class ~ '^[ABCDEFG]$'),

  -- Financier (saisie terrain / desk)
  purchase_price_target numeric(14, 2),
  resale_price_estimate numeric(14, 2),
  dvf_reference_price_m2 numeric(14, 2),
  works_estimate_total numeric(14, 2) not null default 0,
  works_visit_adjustment numeric(14, 2) not null default 0,

  notary_fee_rate numeric(6, 5) not null default 0.077,
  sale_agency_fee_rate numeric(6, 5) not null default 0.05,
  misc_acquisition_cost numeric(14, 2) not null default 0,
  misc_sale_cost numeric(14, 2) not null default 0,

  carrying_months smallint not null default 6,
  carrying_annual_rate numeric(6, 5) not null default 0.05,
  carrying_principal numeric(14, 2),

  -- Urbanisme & stratégies "quick win"
  plu_zone_code text,
  plu_notes text,
  parcel_subdivision_candidate boolean not null default false,
  deficit_foncier_candidate boolean not null default false,

  -- IA (agents) — JSON pour itérer vite sans migrations à chaque prompt
  sourcing_agent_output jsonb,
  tech_estimator_output jsonb,
  financier_agent_output jsonb,
  deal_maker_output jsonb,

  under_promise_at timestamptz,
  teaser_pdf_url text,

  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create index if not exists dossiers_user_id_idx on public.dossiers (user_id);
create index if not exists dossiers_status_idx on public.dossiers (status);

-- ---------------------------------------------------------------------------
-- Catalogue "points noirs" visite (anti-erreur)
-- ---------------------------------------------------------------------------
create table if not exists public.visit_finding_definitions (
  code text primary key,
  label text not null,
  default_works_delta_eur numeric(14, 2) not null default 0,
  severity smallint not null default 1,
  sort_order int not null default 0
);

insert into public.visit_finding_definitions (code, label, default_works_delta_eur, severity, sort_order)
values
  ('structural_crack', 'Fissure structurelle / désordre porteur', 15000, 5, 10),
  ('roof_full_replace', 'Toiture à refaire (complète)', 35000, 5, 20),
  ('roof_partial', 'Toiture partielle / zinguerie lourde', 8000, 3, 30),
  ('humidity_basement', 'Infiltrations cave / vide sanitaire', 12000, 3, 40),
  ('electrical_rewire', 'Rénovation électrique complète', 15000, 4, 50),
  ('asbestos', 'Présence amiante / désamiantage à prévoir', 10000, 4, 60),
  ('septic_non_conform', 'Assainissement non conforme', 12000, 3, 70),
  ('facade_insulation', 'ITE / ravalement lourd', 25000, 3, 80),
  ('heat_pump_full', 'Chauffage à refaire (pompe à chaleur + réseau)', 18000, 2, 90)
on conflict (code) do nothing;

create table if not exists public.dossier_visit_findings (
  id uuid primary key default gen_random_uuid(),
  dossier_id uuid not null references public.dossiers (id) on delete cascade,
  finding_code text not null references public.visit_finding_definitions (code),
  checked boolean not null default false,
  works_delta_override_eur numeric(14, 2),
  checked_at timestamptz,
  unique (dossier_id, finding_code)
);

create index if not exists dossier_visit_findings_dossier_idx
  on public.dossier_visit_findings (dossier_id);

-- ---------------------------------------------------------------------------
-- Investisseurs (module "Flash" — critères en JSON)
-- ---------------------------------------------------------------------------
create table if not exists public.investisseurs (
  id uuid primary key default gen_random_uuid(),
  user_id uuid not null references auth.users (id) on delete cascade,
  display_name text not null,
  email text,
  phone text,
  min_margin_pct numeric(5, 2) not null default 12,
  max_ticket_eur numeric(14, 2),
  zones jsonb,
  strategies jsonb,
  notes text,
  created_at timestamptz not null default now(),
  updated_at timestamptz not null default now()
);

create index if not exists investisseurs_user_id_idx on public.investisseurs (user_id);

-- ---------------------------------------------------------------------------
-- updated_at trigger
-- ---------------------------------------------------------------------------
create or replace function public.set_updated_at()
returns trigger language plpgsql as $$
begin
  new.updated_at = now();
  return new;
end;
$$;

drop trigger if exists set_profiles_updated_at on public.profiles;
create trigger set_profiles_updated_at
before update on public.profiles
for each row execute procedure public.set_updated_at();

drop trigger if exists set_dossiers_updated_at on public.dossiers;
create trigger set_dossiers_updated_at
before update on public.dossiers
for each row execute procedure public.set_updated_at();

drop trigger if exists set_investisseurs_updated_at on public.investisseurs;
create trigger set_investisseurs_updated_at
before update on public.investisseurs
for each row execute procedure public.set_updated_at();

-- ---------------------------------------------------------------------------
-- RLS
-- ---------------------------------------------------------------------------
alter table public.profiles enable row level security;
alter table public.dossiers enable row level security;
alter table public.dossier_visit_findings enable row level security;
alter table public.investisseurs enable row level security;

-- lecture / écriture : uniquement son user_id
create policy "profiles_self" on public.profiles
  for all using (auth.uid() = id) with check (auth.uid() = id);

create policy "dossiers_self" on public.dossiers
  for all using (auth.uid() = user_id) with check (auth.uid() = user_id);

create policy "visit_findings_via_dossier" on public.dossier_visit_findings
  for all using (
    exists (
      select 1 from public.dossiers d
      where d.id = dossier_id and d.user_id = auth.uid()
    )
  )
  with check (
    exists (
      select 1 from public.dossiers d
      where d.id = dossier_id and d.user_id = auth.uid()
    )
  );

create policy "investisseurs_self" on public.investisseurs
  for all using (auth.uid() = user_id) with check (auth.uid() = user_id);

-- Catalogue visites : lecture pour tous utilisateurs authentifiés
alter table public.visit_finding_definitions enable row level security;
create policy "visit_finding_definitions_read" on public.visit_finding_definitions
  for select to authenticated using (true);

-- ---------------------------------------------------------------------------
-- Auto-création profil à l'inscription (optionnel)
-- ---------------------------------------------------------------------------
create or replace function public.handle_new_user()
returns trigger language plpgsql security definer set search_path = public as $$
begin
  insert into public.profiles (id, full_name)
  values (new.id, coalesce(new.raw_user_meta_data->>'full_name', ''))
  on conflict (id) do nothing;
  return new;
end;
$$;

drop trigger if exists mdb_on_auth_user_created on auth.users;
create trigger mdb_on_auth_user_created
after insert on auth.users
for each row execute procedure public.handle_new_user();
