-- VYNDR Web — user profile + scan throttle + parlay leg frequency
-- Idempotent. Safe to apply multiple times.

create extension if not exists "pgcrypto";

-- ────────────────────────────────────────────────────────────
-- user_profiles
-- ────────────────────────────────────────────────────────────
create table if not exists public.user_profiles (
  id                    uuid primary key references auth.users(id) on delete cascade,
  email                 text,
  tier                  text not null default 'free' check (tier in ('free', 'analyst', 'desk')),
  scan_count            integer not null default 0,
  scan_reset_date       date    not null default current_date,
  subscription_start    timestamptz,
  subscription_end      timestamptz,
  subscription_status   text    not null default 'none' check (subscription_status in ('none','active','grace_period','expired','canceled')),
  cancel_at_period_end  boolean not null default false,
  founder_pricing       boolean not null default false,
  age_verified          boolean not null default false,
  nexapay_customer_id   text,
  created_at            timestamptz not null default now(),
  updated_at            timestamptz not null default now()
);

create index if not exists idx_user_profiles_tier on public.user_profiles(tier);
create index if not exists idx_user_profiles_subscription_end on public.user_profiles(subscription_end);

-- Auto-create profile on auth.users insert
create or replace function public.handle_new_user()
returns trigger as $$
begin
  insert into public.user_profiles (id, email)
  values (new.id, new.email)
  on conflict (id) do nothing;
  return new;
end;
$$ language plpgsql security definer set search_path = public;

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

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

drop trigger if exists set_user_profiles_updated_at on public.user_profiles;
create trigger set_user_profiles_updated_at
  before update on public.user_profiles
  for each row execute function public.touch_updated_at();

-- RLS
alter table public.user_profiles enable row level security;

drop policy if exists "user can read own profile" on public.user_profiles;
create policy "user can read own profile"
  on public.user_profiles for select
  using (auth.uid() = id);

drop policy if exists "user can update own profile" on public.user_profiles;
create policy "user can update own profile"
  on public.user_profiles for update
  using (auth.uid() = id)
  with check (auth.uid() = id);

-- service role bypasses RLS automatically; no explicit policy needed.

-- ────────────────────────────────────────────────────────────
-- parlay_leg_frequency — track scan + parlay popularity per day
-- ────────────────────────────────────────────────────────────
create table if not exists public.parlay_leg_frequency (
  id           uuid primary key default gen_random_uuid(),
  player_name  text   not null,
  stat         text   not null,
  line         numeric not null,
  over_under   text   not null check (over_under in ('over','under')),
  sport        text   not null check (sport in ('NBA','MLB','WNBA','NFL')),
  game_date    date   not null default current_date,
  scan_count   integer not null default 0,
  parlay_count integer not null default 0,
  created_at   timestamptz not null default now(),
  updated_at   timestamptz not null default now(),
  unique (player_name, stat, line, over_under, sport, game_date)
);

create index if not exists idx_plf_game_date_sport on public.parlay_leg_frequency(game_date, sport);
create index if not exists idx_plf_parlay_rank on public.parlay_leg_frequency(game_date, parlay_count desc);
create index if not exists idx_plf_scan_rank on public.parlay_leg_frequency(game_date, scan_count desc);

drop trigger if exists set_plf_updated_at on public.parlay_leg_frequency;
create trigger set_plf_updated_at
  before update on public.parlay_leg_frequency
  for each row execute function public.touch_updated_at();

-- Public read; writes restricted to service role
alter table public.parlay_leg_frequency enable row level security;

drop policy if exists "anyone can read parlay frequency" on public.parlay_leg_frequency;
create policy "anyone can read parlay frequency"
  on public.parlay_leg_frequency for select
  using (true);

-- Atomic increment helper
create or replace function public.increment_parlay_leg_frequency(
  p_player text,
  p_stat   text,
  p_line   numeric,
  p_dir    text,
  p_sport  text,
  p_scan_delta integer default 0,
  p_parlay_delta integer default 0
) returns void as $$
begin
  insert into public.parlay_leg_frequency
    (player_name, stat, line, over_under, sport, scan_count, parlay_count)
  values
    (p_player, p_stat, p_line, p_dir, p_sport, p_scan_delta, p_parlay_delta)
  on conflict (player_name, stat, line, over_under, sport, game_date)
  do update set
    scan_count   = public.parlay_leg_frequency.scan_count + p_scan_delta,
    parlay_count = public.parlay_leg_frequency.parlay_count + p_parlay_delta,
    updated_at   = now();
end;
$$ language plpgsql security definer set search_path = public;

-- ────────────────────────────────────────────────────────────
-- scan_history — for ledger + per-user analytics
-- ────────────────────────────────────────────────────────────
create table if not exists public.scan_history (
  id          uuid primary key default gen_random_uuid(),
  user_id     uuid references auth.users(id) on delete set null,
  sport       text not null,
  player_name text not null,
  stat        text not null,
  line        numeric not null,
  direction   text not null,
  grade       text,
  projection  numeric,
  confidence  integer,
  factors     jsonb,
  created_at  timestamptz not null default now()
);

create index if not exists idx_scan_history_user on public.scan_history(user_id, created_at desc);
create index if not exists idx_scan_history_sport on public.scan_history(sport, created_at desc);

alter table public.scan_history enable row level security;

drop policy if exists "user reads own scans" on public.scan_history;
create policy "user reads own scans"
  on public.scan_history for select
  using (auth.uid() = user_id);

drop policy if exists "user inserts own scans" on public.scan_history;
create policy "user inserts own scans"
  on public.scan_history for insert
  with check (auth.uid() = user_id);
