-- Flux opportunités aspirées + agent Scout (batch JSON côté Postgres)

create table if not exists public.deals_sources (
  id uuid primary key default gen_random_uuid(),
  user_id uuid not null references auth.users (id) on delete cascade,
  title text not null,
  description text,
  source_url text,
  source_name text,
  price_eur numeric(14, 2),
  surface_m2 numeric(12, 2) not null,
  price_per_m2_eur numeric(14, 2) not null,
  dvf_avg_m2_simulated numeric(14, 2) not null default 3500,
  distress_keywords text[] not null default '{}',
  opportunity_score numeric(6, 2) not null,
  grade text not null check (grade in ('A', 'B', 'C')),
  raw_payload jsonb,
  created_at timestamptz not null default now()
);

create index if not exists deals_sources_user_score_idx
  on public.deals_sources (user_id, opportunity_score desc);
create index if not exists deals_sources_user_created_idx
  on public.deals_sources (user_id, created_at desc);

alter table public.profiles add column if not exists expo_push_token text;

-- Activer Realtime sur cette table : Dashboard Supabase → Realtime → ajouter public.deals_sources

alter table public.deals_sources enable row level security;

create policy deals_sources_select_own on public.deals_sources
  for select to authenticated
  using (auth.uid() = user_id);

-- Pas d’INSERT direct : uniquement via la fonction SECURITY DEFINER ci-dessous.

create or replace function public.scout_process_batch(p_listings jsonb)
returns jsonb
language plpgsql
security definer
set search_path = public
as $$
declare
  uid uuid := auth.uid();
  el jsonb;
  txt text;
  price numeric;
  surf numeric;
  pm2 numeric;
  avg_m2 constant numeric := 3500;
  keywords text[] := array['succession', 'urgent', 'travaux important'];
  k text;
  matched text[];
  ok_kw boolean;
  ok_pm2 boolean;
  score numeric;
  grade text;
  n int := 0;
  na int := 0;
begin
  if uid is null then
    raise exception 'scout_process_batch: non authentifié';
  end if;

  for el in select * from jsonb_array_elements(coalesce(p_listings, '[]'::jsonb))
  loop
    txt := lower(
      coalesce(el ->> 'description', '') || ' ' || coalesce(el ->> 'title', '')
    );
    price := nullif(trim(el ->> 'price_eur'), '')::numeric;
    surf := nullif(trim(el ->> 'surface_m2'), '')::numeric;

    if price is null or surf is null or surf <= 0 then
      continue;
    end if;

    pm2 := price / surf;
    matched := array[]::text[];
    ok_kw := false;

    foreach k in array keywords
    loop
      if strpos(txt, k) > 0 then
        ok_kw := true;
        matched := array_append(matched, k);
      end if;
    end loop;

    ok_pm2 := pm2 < avg_m2;

    if not (ok_kw and ok_pm2) then
      continue;
    end if;

    score := 40::numeric
      + greatest(0::numeric, (avg_m2 - pm2) / nullif(avg_m2, 0) * 50)
      + coalesce(array_length(matched, 1), 0) * 10;

    grade := case
      when score >= 80 then 'A'
      when score >= 55 then 'B'
      else 'C'
    end;

    insert into public.deals_sources (
      user_id,
      title,
      description,
      source_url,
      source_name,
      price_eur,
      surface_m2,
      price_per_m2_eur,
      dvf_avg_m2_simulated,
      distress_keywords,
      opportunity_score,
      grade,
      raw_payload
    )
    values (
      uid,
      coalesce(nullif(trim(el ->> 'title'), ''), 'Sans titre'),
      el ->> 'description',
      nullif(trim(el ->> 'url'), ''),
      nullif(trim(el ->> 'source'), ''),
      price,
      surf,
      pm2,
      avg_m2,
      matched,
      score,
      grade,
      el
    );

    n := n + 1;
    if grade = 'A' then
      na := na + 1;
    end if;
  end loop;

  return jsonb_build_object(
    'inserted_count', n,
    'grade_a_count', na,
    'simulated_dvf_avg_m2', avg_m2
  );
end;
$$;

grant execute on function public.scout_process_batch(jsonb) to authenticated;

comment on function public.scout_process_batch(jsonb) is
  'Filtre un lot JSON d''annonces (mots-clés détresse + prix/m² < moyenne simulée) et insère dans deals_sources.';
