import { createServerFn } from "@tanstack/react-start";
import { requireSupabaseAuth } from "@/integrations/supabase/auth-middleware";

async function assertAdmin(supabase: { rpc: (fn: string, args: unknown) => Promise<{ data: unknown; error: unknown }> }, userId: string) {
  const { data, error } = await supabase.rpc("has_role", { _user_id: userId, _role: "admin" });
  if (error) throw new Error((error as { message: string }).message);
  if (!data) throw new Error("Forbidden — admin only");
}

export interface EventCountRow {
  event: string;
  day: string;
  count: number;
}

export interface AiKindStats {
  kind: string;
  total: number;
  ok: number;
  errors: number;
  rate_limited: number;
  validation_failed: number;
  avg_latency_ms: number | null;
  total_tokens: number | null;
}

export interface AdminAnalyticsSummary {
  events: EventCountRow[];
  ai: AiKindStats[];
  totals: {
    signups: number;
    logins: number;
    plansGenerated: number;
    plansSaved: number;
    pdfExports: number;
    upgradeClicks: number;
    checkouts: number;
  };
  activationRate: number; // signups → first plan saved
}

export const getAdminAnalytics = createServerFn({ method: "GET" })
  .middleware([requireSupabaseAuth])
  .handler(async ({ context }): Promise<AdminAnalyticsSummary> => {
    await assertAdmin(context.supabase as never, context.userId);
    const { supabaseAdmin } = await import("@/integrations/supabase/client.server");

    // Last 30 days, by event/day
    const since = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000).toISOString();
    const { data: eventsRaw, error: evErr } = await supabaseAdmin
      .from("analytics_events")
      .select("event,created_at")
      .gte("created_at", since)
      .limit(20000);
    if (evErr) throw new Error(evErr.message);

    const byKey = new Map<string, { event: string; day: string; count: number }>();
    const totals = {
      signups: 0, logins: 0, plansGenerated: 0, plansSaved: 0,
      pdfExports: 0, upgradeClicks: 0, checkouts: 0,
    };
    for (const r of eventsRaw ?? []) {
      const day = (r.created_at as string).slice(0, 10);
      const key = `${r.event}__${day}`;
      const cur = byKey.get(key);
      if (cur) cur.count += 1;
      else byKey.set(key, { event: r.event as string, day, count: 1 });
      switch (r.event) {
        case "signup": totals.signups++; break;
        case "login": totals.logins++; break;
        case "photoshoot_plan_generated": totals.plansGenerated++; break;
        case "plan_saved": totals.plansSaved++; break;
        case "pdf_exported": totals.pdfExports++; break;
        case "upgrade_clicked": totals.upgradeClicks++; break;
        case "checkout_completed": totals.checkouts++; break;
      }
    }
    const events = Array.from(byKey.values()).sort((a, b) =>
      a.day === b.day ? a.event.localeCompare(b.event) : a.day < b.day ? 1 : -1,
    );

    // AI stats by kind
    const { data: aiRaw, error: aiErr } = await supabaseAdmin
      .from("ai_request_log")
      .select("kind,status,latency_ms,total_tokens,created_at")
      .gte("created_at", since)
      .limit(20000);
    if (aiErr) throw new Error(aiErr.message);

    const aiMap = new Map<string, AiKindStats & { _latencies: number[] }>();
    for (const r of aiRaw ?? []) {
      const k = r.kind as string;
      let s = aiMap.get(k);
      if (!s) {
        s = {
          kind: k, total: 0, ok: 0, errors: 0, rate_limited: 0,
          validation_failed: 0, avg_latency_ms: null, total_tokens: 0,
          _latencies: [],
        };
        aiMap.set(k, s);
      }
      s.total++;
      if (r.status === "ok") s.ok++;
      else if (r.status === "error") s.errors++;
      else if (r.status === "rate_limited") s.rate_limited++;
      else if (r.status === "validation_failed") s.validation_failed++;
      if (typeof r.latency_ms === "number") s._latencies.push(r.latency_ms);
      if (typeof r.total_tokens === "number") s.total_tokens = (s.total_tokens ?? 0) + r.total_tokens;
    }
    const ai = Array.from(aiMap.values()).map((s) => ({
      kind: s.kind,
      total: s.total,
      ok: s.ok,
      errors: s.errors,
      rate_limited: s.rate_limited,
      validation_failed: s.validation_failed,
      avg_latency_ms: s._latencies.length
        ? Math.round(s._latencies.reduce((a, b) => a + b, 0) / s._latencies.length)
        : null,
      total_tokens: s.total_tokens,
    }));

    const activationRate = totals.signups > 0 ? totals.plansSaved / totals.signups : 0;

    return { events, ai, totals, activationRate };
  });
