-- VYNDR Initial Schema
-- Feature 1.4 — All tables, indexes, RLS policies, triggers
-- All timestamps use TIMESTAMPTZ (UTC)

-- ============================================================
-- TABLE: users
-- Extends auth.users with app-specific profile data
-- ============================================================
CREATE TABLE public.users (
  id UUID PRIMARY KEY REFERENCES auth.users(id) ON DELETE CASCADE,
  email TEXT NOT NULL,
  tier TEXT NOT NULL DEFAULT 'free' CHECK (tier IN ('free', 'analyst', 'desk')),
  scan_count INT NOT NULL DEFAULT 0,
  scan_reset_date TIMESTAMPTZ NOT NULL DEFAULT (date_trunc('month', now()) + interval '1 month'),
  stripe_customer_id TEXT,
  founder_status BOOLEAN NOT NULL DEFAULT false,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

ALTER TABLE public.users ENABLE ROW LEVEL SECURITY;

CREATE POLICY "users_select_own" ON public.users
  FOR SELECT USING (auth.uid() = id);

CREATE POLICY "users_update_own" ON public.users
  FOR UPDATE USING (auth.uid() = id)
  WITH CHECK (auth.uid() = id);

CREATE POLICY "users_insert_own" ON public.users
  FOR INSERT WITH CHECK (auth.uid() = id);

-- ============================================================
-- TABLE: picks
-- Individual prop analysis results from scans
-- ============================================================
CREATE TABLE public.picks (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
  player TEXT NOT NULL,
  stat_type TEXT NOT NULL,
  line NUMERIC(5,1) NOT NULL,
  book TEXT NOT NULL,
  direction TEXT NOT NULL CHECK (direction IN ('over', 'under')),
  grade TEXT NOT NULL CHECK (grade IN ('A', 'B', 'C', 'D')),
  edge_pct NUMERIC(5,2),
  reasoning TEXT,
  kill_conditions TEXT[],
  confidence NUMERIC(4,2),
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_picks_user_id ON public.picks(user_id);
CREATE INDEX idx_picks_created_at ON public.picks(created_at);

ALTER TABLE public.picks ENABLE ROW LEVEL SECURITY;

CREATE POLICY "picks_select_own" ON public.picks
  FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "picks_insert_own" ON public.picks
  FOR INSERT WITH CHECK (auth.uid() = user_id);

-- ============================================================
-- TABLE: scan_sessions
-- Groups picks into a single scan/parlay analysis session
-- ============================================================
CREATE TABLE public.scan_sessions (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
  legs UUID[] NOT NULL DEFAULT '{}',
  final_grade TEXT CHECK (final_grade IN ('A', 'B', 'C', 'D')),
  kill_conditions TEXT[],
  correlation_notes TEXT,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_scan_sessions_user_id ON public.scan_sessions(user_id);

ALTER TABLE public.scan_sessions ENABLE ROW LEVEL SECURITY;

CREATE POLICY "scan_sessions_select_own" ON public.scan_sessions
  FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "scan_sessions_insert_own" ON public.scan_sessions
  FOR INSERT WITH CHECK (auth.uid() = user_id);

-- ============================================================
-- TABLE: bets
-- User-submitted bets (screenshot, quick slip, sportsbook sync)
-- ============================================================
CREATE TABLE public.bets (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
  amount NUMERIC(10,2) NOT NULL,
  potential_payout NUMERIC(10,2),
  slip_data JSONB NOT NULL,
  book TEXT NOT NULL,
  bet_type TEXT NOT NULL CHECK (bet_type IN ('straight', 'parlay', 'teaser', 'round_robin')),
  submission_method TEXT NOT NULL CHECK (submission_method IN ('screenshot', 'quickslip', 'sync')),
  status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'won', 'lost', 'push', 'void')),
  placed_at TIMESTAMPTZ NOT NULL DEFAULT now(),
  settled_at TIMESTAMPTZ,
  created_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_bets_user_id ON public.bets(user_id);
CREATE INDEX idx_bets_status ON public.bets(status);
CREATE INDEX idx_bets_placed_at ON public.bets(placed_at);

ALTER TABLE public.bets ENABLE ROW LEVEL SECURITY;

CREATE POLICY "bets_select_own" ON public.bets
  FOR SELECT USING (auth.uid() = user_id);

CREATE POLICY "bets_insert_own" ON public.bets
  FOR INSERT WITH CHECK (auth.uid() = user_id);

CREATE POLICY "bets_update_own" ON public.bets
  FOR UPDATE USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);

-- ============================================================
-- TABLE: outcomes
-- Actual results for each pick after game is played
-- ============================================================
CREATE TABLE public.outcomes (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  pick_id UUID NOT NULL REFERENCES public.picks(id) ON DELETE CASCADE,
  result TEXT NOT NULL CHECK (result IN ('hit', 'miss', 'push')),
  actual_value NUMERIC(5,1) NOT NULL,
  logged_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE UNIQUE INDEX idx_outcomes_pick_id ON public.outcomes(pick_id);

ALTER TABLE public.outcomes ENABLE ROW LEVEL SECURITY;

CREATE POLICY "outcomes_select_own" ON public.outcomes
  FOR SELECT USING (
    EXISTS (
      SELECT 1 FROM public.picks
      WHERE picks.id = outcomes.pick_id AND picks.user_id = auth.uid()
    )
  );

-- ============================================================
-- TABLE: performance
-- Aggregated performance metrics per user per period
-- ============================================================
CREATE TABLE public.performance (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  user_id UUID NOT NULL REFERENCES public.users(id) ON DELETE CASCADE,
  period TEXT NOT NULL CHECK (period IN ('weekly', 'monthly', 'all_time')),
  roi NUMERIC(6,2),
  win_rate NUMERIC(5,2),
  sample_size INT NOT NULL DEFAULT 0,
  total_wagered NUMERIC(10,2) DEFAULT 0,
  total_profit NUMERIC(10,2) DEFAULT 0,
  calculated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

CREATE INDEX idx_performance_user_id ON public.performance(user_id);
CREATE UNIQUE INDEX idx_performance_user_period ON public.performance(user_id, period);

ALTER TABLE public.performance ENABLE ROW LEVEL SECURITY;

CREATE POLICY "performance_select_own" ON public.performance
  FOR SELECT USING (auth.uid() = user_id);

-- ============================================================
-- TRIGGERS
-- ============================================================

-- 1. Auto-create user profile on signup
CREATE OR REPLACE FUNCTION public.handle_new_user()
RETURNS TRIGGER AS $$
BEGIN
  INSERT INTO public.users (id, email)
  VALUES (NEW.id, NEW.email);
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE TRIGGER on_auth_user_created
  AFTER INSERT ON auth.users
  FOR EACH ROW EXECUTE FUNCTION public.handle_new_user();

-- 2. Auto-update updated_at on users table
CREATE OR REPLACE FUNCTION public.update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = now();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER users_updated_at
  BEFORE UPDATE ON public.users
  FOR EACH ROW EXECUTE FUNCTION public.update_updated_at();

-- 3. Monthly scan count reset
CREATE OR REPLACE FUNCTION public.reset_scan_count()
RETURNS TRIGGER AS $$
BEGIN
  IF NEW.scan_reset_date <= now() THEN
    NEW.scan_count = 0;
    NEW.scan_reset_date = date_trunc('month', now()) + interval '1 month';
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER users_scan_reset
  BEFORE UPDATE ON public.users
  FOR EACH ROW EXECUTE FUNCTION public.reset_scan_count();
