import { NextResponse } from "next/server";
import { requireAdmin } from "@/lib/admin-auth";
import { sql } from "@/db";

// Engagement / analytics feed for /admin/analytics.
//
// Each section runs in its own try/catch and pushes any failure into `errors`,
// so a single broken query degrades gracefully (partial data still renders)
// AND the real error message is surfaced on the page instead of a silent blank.
export async function GET(request: Request) {
  const auth = await requireAdmin(request);
  if (!auth.success) return NextResponse.json({ error: auth.error }, { status: auth.status });

  const errors: string[] = [];
  let total = 0;
  let featureAdoption: { name: string; count: number; pct: number }[] = [];
  let families: Array<Record<string, unknown>> = [];
  let aiUsage = { totalCalls: 0, totalTokens: 0, totalCostPaise: 0, familiesUsingAI: 0 };
  let logsByDay: { date: string; count: number }[] = [];

  // 0. Total families (cheap, robust — used for denominators + summary total)
  try {
    const rows = await sql`SELECT COUNT(*)::int AS count FROM families`;
    total = Number(rows[0]?.count) || 0;
  } catch (e) {
    errors.push(`families_count: ${String(e)}`);
  }

  // A. Feature adoption — % of families that have used each feature at least once
  try {
    const adoptionRows = await sql`
      SELECT
        COUNT(DISTINCT f.id) FILTER (WHERE fd.id IS NOT NULL)::int as families_feeding,
        COUNT(DISTINCT f.id) FILTER (WHERE dl.id IS NOT NULL)::int as families_diapers,
        COUNT(DISTINCT f.id) FILTER (WHERE sl.id IS NOT NULL)::int as families_sleeping,
        COUNT(DISTINCT f.id) FILTER (WHERE v.id IS NOT NULL)::int as families_vaccinating,
        COUNT(DISTINCT f.id) FILTER (WHERE g.id IS NOT NULL)::int as families_growth,
        COUNT(DISTINCT f.id) FILTER (WHERE mem.id IS NOT NULL)::int as families_memories,
        COUNT(DISTINCT f.id) FILTER (WHERE cs.id IS NOT NULL)::int as families_ai
      FROM families f
      LEFT JOIN children c ON c.family_id = f.id
      LEFT JOIN LATERAL (SELECT id FROM feeds WHERE child_id = c.id LIMIT 1) fd ON true
      LEFT JOIN LATERAL (SELECT id FROM diapers_logs WHERE child_id = c.id LIMIT 1) dl ON true
      LEFT JOIN LATERAL (SELECT id FROM sleeps WHERE child_id = c.id LIMIT 1) sl ON true
      LEFT JOIN LATERAL (SELECT id FROM vaccinations WHERE child_id = c.id LIMIT 1) v ON true
      LEFT JOIN LATERAL (SELECT id FROM growth WHERE child_id = c.id LIMIT 1) g ON true
      LEFT JOIN LATERAL (SELECT id FROM memories WHERE family_id = f.id LIMIT 1) mem ON true
      LEFT JOIN LATERAL (SELECT id FROM chat_sessions WHERE child_id = c.id LIMIT 1) cs ON true
    `;
    const a = adoptionRows[0] || {};
    const denom = total || 1;
    const pct = (n: unknown) => Math.round((Number(n) || 0) / denom * 100);
    featureAdoption = [
      { name: "Feed Logs", count: Number(a.families_feeding) || 0, pct: pct(a.families_feeding) },
      { name: "Diaper Logs", count: Number(a.families_diapers) || 0, pct: pct(a.families_diapers) },
      { name: "Sleep Logs", count: Number(a.families_sleeping) || 0, pct: pct(a.families_sleeping) },
      { name: "Vaccinations", count: Number(a.families_vaccinating) || 0, pct: pct(a.families_vaccinating) },
      { name: "Growth Tracking", count: Number(a.families_growth) || 0, pct: pct(a.families_growth) },
      { name: "Memories", count: Number(a.families_memories) || 0, pct: pct(a.families_memories) },
      { name: "AI Chat", count: Number(a.families_ai) || 0, pct: pct(a.families_ai) },
    ].sort((x, y) => y.pct - x.pct);
  } catch (e) {
    errors.push(`feature_adoption: ${String(e)}`);
  }

  // B. Per-family engagement table.
  //
  // Pre-aggregate each log table to one row per child BEFORE joining — joining
  // the raw tables together produces a cartesian product that times out in
  // production. Memories are per-family. All MAX(*) timestamps are cast to
  // timestamptz so GREATEST() can't choke on mixed timestamp/timestamptz types.
  try {
    const familyRows = await sql`
      WITH feed_agg   AS (SELECT child_id, COUNT(*)::int AS cnt, MAX(logged_at)  AS last_at FROM feeds        GROUP BY child_id),
           diaper_agg AS (SELECT child_id, COUNT(*)::int AS cnt, MAX(logged_at)  AS last_at FROM diapers_logs GROUP BY child_id),
           sleep_agg  AS (SELECT child_id, COUNT(*)::int AS cnt, MAX(started_at) AS last_at FROM sleeps       GROUP BY child_id),
           vacc_agg   AS (SELECT child_id, COUNT(*)::int AS cnt FROM vaccinations  GROUP BY child_id),
           growth_agg AS (SELECT child_id, COUNT(*)::int AS cnt FROM growth        GROUP BY child_id),
           chat_agg   AS (SELECT child_id, COUNT(*)::int AS cnt FROM chat_sessions GROUP BY child_id),
           mem_agg    AS (SELECT family_id, COUNT(*)::int AS cnt, MAX(created_at) AS last_at FROM memories GROUP BY family_id)
      SELECT
        f.id,
        f.name,
        f.tier,
        f.created_at,
        GREATEST(
          MAX(fa.last_at)::timestamptz,
          MAX(da.last_at)::timestamptz,
          MAX(sa.last_at)::timestamptz,
          MAX(ma.last_at)::timestamptz
        ) as last_activity,
        COALESCE(SUM(fa.cnt), 0)::int as feed_count,
        COALESCE(SUM(da.cnt), 0)::int as diaper_count,
        COALESCE(SUM(sa.cnt), 0)::int as sleep_count,
        COALESCE(SUM(va.cnt), 0)::int as vaccination_count,
        COALESCE(SUM(ga.cnt), 0)::int as growth_count,
        COALESCE(MAX(ma.cnt), 0)::int as memory_count,
        COALESCE(SUM(ca.cnt), 0)::int as chat_count
      FROM families f
      LEFT JOIN children c    ON c.family_id = f.id
      LEFT JOIN feed_agg fa   ON fa.child_id = c.id
      LEFT JOIN diaper_agg da ON da.child_id = c.id
      LEFT JOIN sleep_agg sa  ON sa.child_id = c.id
      LEFT JOIN vacc_agg va   ON va.child_id = c.id
      LEFT JOIN growth_agg ga ON ga.child_id = c.id
      LEFT JOIN chat_agg ca   ON ca.child_id = c.id
      LEFT JOIN mem_agg ma    ON ma.family_id = f.id
      GROUP BY f.id, f.name, f.tier, f.created_at
      ORDER BY last_activity DESC NULLS LAST
    `;

    const now = Date.now();
    families = familyRows.map((f: Record<string, unknown>) => {
      const lastActivity = f.last_activity ? new Date(f.last_activity as string).toISOString() : null;
      const msSince = lastActivity ? now - new Date(lastActivity).getTime() : Infinity;
      const activeStatus = !lastActivity ? "never" : msSince < 7 * 86400_000 ? "7d" : msSince < 30 * 86400_000 ? "30d" : "inactive";
      return {
        id: f.id,
        name: f.name,
        tier: f.tier || "free",
        createdAt: f.created_at ? new Date(f.created_at as string).toISOString() : null,
        lastActivity,
        activeStatus,
        feedCount: Number(f.feed_count) || 0,
        diaperCount: Number(f.diaper_count) || 0,
        sleepCount: Number(f.sleep_count) || 0,
        vaccinationCount: Number(f.vaccination_count) || 0,
        growthCount: Number(f.growth_count) || 0,
        memoryCount: Number(f.memory_count) || 0,
        chatCount: Number(f.chat_count) || 0,
        totalLogs:
          (Number(f.feed_count) || 0) + (Number(f.diaper_count) || 0) + (Number(f.sleep_count) || 0) +
          (Number(f.vaccination_count) || 0) + (Number(f.growth_count) || 0),
      };
    });
    if (!total) total = families.length;
  } catch (e) {
    errors.push(`families: ${String(e)}`);
  }

  // C. Activity summary counts (derived from families)
  const active7d = families.filter(f => f.activeStatus === "7d").length;
  const active30d = families.filter(f => f.activeStatus === "30d").length;
  const neverActive = families.filter(f => f.activeStatus === "never").length;

  // D. AI usage last 30 days
  try {
    const aiRows = await sql`
      SELECT
        COUNT(*)::int as total_calls,
        COALESCE(SUM(total_tokens), 0)::int as total_tokens,
        COALESCE(SUM(cost_estimate_paise), 0)::numeric as total_cost_paise,
        COUNT(DISTINCT family_id)::int as families_using_ai
      FROM ai_usage
      WHERE created_at > NOW() - INTERVAL '30 days'
    `;
    const row = aiRows[0] || {};
    aiUsage = {
      totalCalls: Number(row.total_calls) || 0,
      totalTokens: Number(row.total_tokens) || 0,
      totalCostPaise: Number(row.total_cost_paise) || 0,
      familiesUsingAI: Number(row.families_using_ai) || 0,
    };
  } catch (e) {
    errors.push(`ai_usage: ${String(e)}`);
  }

  // E. Daily activity for chart (last 30 days, all log types combined)
  try {
    const dailyRows = await sql`
      SELECT day::date as date, SUM(cnt)::int as count
      FROM (
        SELECT DATE(logged_at) as day, COUNT(*) as cnt FROM feeds WHERE logged_at > NOW() - INTERVAL '30 days' GROUP BY day
        UNION ALL
        SELECT DATE(logged_at) as day, COUNT(*) as cnt FROM diapers_logs WHERE logged_at > NOW() - INTERVAL '30 days' GROUP BY day
        UNION ALL
        SELECT DATE(started_at) as day, COUNT(*) as cnt FROM sleeps WHERE started_at > NOW() - INTERVAL '30 days' GROUP BY day
        UNION ALL
        SELECT DATE(created_at) as day, COUNT(*) as cnt FROM memories WHERE created_at > NOW() - INTERVAL '30 days' GROUP BY day
      ) sub
      WHERE day IS NOT NULL
      GROUP BY day
      ORDER BY day
    `;
    logsByDay = dailyRows.map((r: Record<string, unknown>) => ({
      date: r.date instanceof Date ? r.date.toISOString().split("T")[0] : String(r.date).split("T")[0],
      count: Number(r.count) || 0,
    }));
  } catch (e) {
    errors.push(`logs_by_day: ${String(e)}`);
  }

  if (errors.length) console.error("Admin engagement partial errors:", errors);

  return NextResponse.json({
    totalFamilies: total,
    featureAdoption,
    families,
    activitySummary: { active7d, active30d, neverActive, total },
    aiUsage,
    logsByDay,
    ...(errors.length ? { error: errors.join(" | ") } : {}),
  });
}
