-- ─────────────────────────────────────────────────────────────────────────────
-- LabCard AI — Supabase Schema
-- Run this in Supabase SQL Editor: https://supabase.com/dashboard/project/_/sql
-- ─────────────────────────────────────────────────────────────────────────────

-- ── User Profiles ─────────────────────────────────────────────────────────────
-- Extends auth.users — created automatically on first report / payment

CREATE TABLE IF NOT EXISTS public.user_profiles (
  id                   UUID         REFERENCES auth.users(id) ON DELETE CASCADE PRIMARY KEY,
  tier                 TEXT         NOT NULL DEFAULT 'free'
                                    CHECK (tier IN ('free', 'premium')),
  reports_analyzed     INTEGER      NOT NULL DEFAULT 0,
  premium_expires_at   TIMESTAMPTZ,
  created_at           TIMESTAMPTZ  DEFAULT NOW(),
  updated_at           TIMESTAMPTZ  DEFAULT NOW()
);

-- Auto-update updated_at on any change
CREATE OR REPLACE FUNCTION update_updated_at()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

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

-- ── Reports ───────────────────────────────────────────────────────────────────
-- Full LabReport JSON stored in report_json JSONB for future trend analysis.
-- Summary columns (score, grade, etc.) allow fast SQL aggregates without
-- parsing the full JSON every time.

CREATE TABLE IF NOT EXISTS public.reports (
  id                   UUID         DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id              UUID         REFERENCES auth.users(id) ON DELETE SET NULL,
  -- Extracted patient fields (denormalized for fast queries)
  patient_name         TEXT,
  patient_age          TEXT,
  patient_gender       TEXT,
  lab_name             TEXT,
  report_date          TEXT,
  -- Health metrics (all deterministic — not from AI)
  health_score         INTEGER      CHECK (health_score >= 0 AND health_score <= 100),
  health_grade         TEXT,
  biological_age       INTEGER,
  chronological_age    INTEGER,
  has_critical_alert   BOOLEAN      DEFAULT FALSE,
  -- Processing metadata
  tier_used            TEXT         DEFAULT 'free',
  biomarker_count      INTEGER,
  abnormal_count       INTEGER,
  processing_time_ms   INTEGER,
  -- Full report blob (enables trend queries + future re-analysis)
  report_json          JSONB        NOT NULL,
  created_at           TIMESTAMPTZ  DEFAULT NOW()
);

-- Indexes for common access patterns
CREATE INDEX IF NOT EXISTS idx_reports_user_id
  ON public.reports(user_id);

CREATE INDEX IF NOT EXISTS idx_reports_created_at
  ON public.reports(created_at DESC);

CREATE INDEX IF NOT EXISTS idx_reports_health_score
  ON public.reports(health_score);

-- GIN index on JSONB for fast biomarker trend queries
CREATE INDEX IF NOT EXISTS idx_reports_json
  ON public.reports USING GIN (report_json);

-- ── Payments ──────────────────────────────────────────────────────────────────
-- Audit trail for all Razorpay transactions.
-- razorpay_order_id is UNIQUE — idempotent upsert is safe.

CREATE TABLE IF NOT EXISTS public.payments (
  id                   UUID         DEFAULT gen_random_uuid() PRIMARY KEY,
  user_id              UUID         REFERENCES auth.users(id) ON DELETE SET NULL,
  razorpay_order_id    TEXT         UNIQUE NOT NULL,
  razorpay_payment_id  TEXT         UNIQUE,
  razorpay_signature   TEXT,
  plan                 TEXT         NOT NULL
                                    CHECK (plan IN ('per_report', 'monthly')),
  amount_paise         INTEGER      NOT NULL,
  status               TEXT         NOT NULL DEFAULT 'pending'
                                    CHECK (status IN ('pending', 'success', 'failed')),
  verified_at          TIMESTAMPTZ,
  created_at           TIMESTAMPTZ  DEFAULT NOW()
);

CREATE INDEX IF NOT EXISTS idx_payments_user_id
  ON public.payments(user_id);

-- ── Row Level Security ────────────────────────────────────────────────────────
-- Users can only read their own data.
-- Backend uses service role key — bypasses RLS for writes.

ALTER TABLE public.user_profiles ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.reports       ENABLE ROW LEVEL SECURITY;
ALTER TABLE public.payments      ENABLE ROW LEVEL SECURITY;

-- user_profiles: users see and update only their own row
CREATE POLICY "Users see own profile"
  ON public.user_profiles FOR ALL
  USING (auth.uid() = id);

-- reports: users can read their own reports
CREATE POLICY "Users see own reports"
  ON public.reports FOR SELECT
  USING (auth.uid() = user_id);

-- reports: backend service role inserts (WITH CHECK true allows service key)
CREATE POLICY "Service role inserts reports"
  ON public.reports FOR INSERT
  WITH CHECK (true);

-- payments: users can only see their own payment records
CREATE POLICY "Users see own payments"
  ON public.payments FOR SELECT
  USING (auth.uid() = user_id);

-- payments: backend service role inserts
CREATE POLICY "Service role inserts payments"
  ON public.payments FOR INSERT
  WITH CHECK (true);

-- ── Helper: increment reports_analyzed counter ────────────────────────────────
-- Called via trigger when a new report is inserted

CREATE OR REPLACE FUNCTION increment_reports_analyzed()
RETURNS TRIGGER AS $$
BEGIN
  IF NEW.user_id IS NOT NULL THEN
    INSERT INTO public.user_profiles (id, reports_analyzed)
      VALUES (NEW.user_id, 1)
      ON CONFLICT (id) DO UPDATE
        SET reports_analyzed = user_profiles.reports_analyzed + 1,
            updated_at = NOW();
  END IF;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;

CREATE TRIGGER on_report_inserted
  AFTER INSERT ON public.reports
  FOR EACH ROW EXECUTE FUNCTION increment_reports_analyzed();

-- ── Trend analysis view (bonus — useful for future dashboard) ─────────────────
-- Returns latest health score per user for trend charts

CREATE OR REPLACE VIEW public.user_health_trends AS
SELECT
  r.user_id,
  r.id           AS report_id,
  r.created_at,
  r.health_score,
  r.health_grade,
  r.biological_age,
  r.chronological_age,
  r.abnormal_count,
  r.lab_name
FROM public.reports r
WHERE r.user_id IS NOT NULL
ORDER BY r.user_id, r.created_at DESC;

-- ── Verify setup ──────────────────────────────────────────────────────────────
SELECT
  schemaname,
  tablename,
  tableowner
FROM pg_tables
WHERE schemaname = 'public'
  AND tablename IN ('user_profiles', 'reports', 'payments');
