/**
 * GET/POST /api/admin/tools?action=…
 *
 * Consolidated admin tools API. Each action maps to a specific tool.
 * All actions require superadmin auth.
 */

import { NextResponse } from "next/server";
import { prisma } from "@/lib/prisma";
import { requireSuperadmin } from "@/lib/admin-auth";
import { backfillMissingQueryContext } from "@/lib/services/ai-referral-backfill";
import { getSourceFreshness } from "@/lib/services/ga4-freshness";

export const dynamic = "force-dynamic";
export const maxDuration = 120;

// ─── GET actions ───────────────────────────────────────────────────────────

export async function GET(req: Request) {
  const denied = await requireSuperadmin();
  if (denied) return denied;

  const action = new URL(req.url).searchParams.get("action");

  if (action === "metric-audit") return metricAudit();
  if (action === "cron-status") return cronStatus();
  if (action === "table-sizes") return tableSizes();
  if (action === "site-tag-health") return siteTagHealth();
  if (action === "brand-status") return brandStatus();
  if (action === "error-log") return errorLog();
  if (action === "source-freshness") return sourceFreshness();

  return NextResponse.json({ error: "Unknown action" }, { status: 400 });
}

// ─── POST actions ──────────────────────────────────────────────────────────

export async function POST(req: Request) {
  const denied = await requireSuperadmin();
  if (denied) return denied;

  const body = await req.json().catch(() => ({})) as Record<string, unknown>;
  const action = body.action as string;

  if (action === "ga4-purge") return ga4Purge(body.brandId as string);
  if (action === "fill-queries") return fillQueries();
  if (action === "test-ai-referral") return testAiReferral(body);
  if (action === "trigger-cron") return triggerCron(body.route as string, req);
  if (action === "clear-errors") return clearErrors();

  return NextResponse.json({ error: "Unknown action" }, { status: 400 });
}

// ─── Metric Audit ──────────────────────────────────────────────────────────

async function metricAudit() {
  const brands = await prisma.brand.findMany({
    where: { status: { not: "deleted" } },
    select: { id: true, name: true, domain: true },
  });

  const rows: Array<{
    brandId: string; name: string; domain: string;
    totalSnapshots: number; dateRange: string;
    totalConversions: number; totalSessions: number;
    status: "healthy" | "suspicious" | "corrupted";
  }> = [];

  for (const brand of brands) {
    const [agg, count, first, last] = await Promise.all([
      prisma.metricSnapshot.aggregate({
        where: { brandId: brand.id, source: "ga4" },
        _sum: { conversions: true, sessions: true },
      }).catch(() => ({ _sum: { conversions: null, sessions: null } })),
      prisma.metricSnapshot.count({ where: { brandId: brand.id } }).catch(() => 0),
      prisma.metricSnapshot.findFirst({ where: { brandId: brand.id }, orderBy: { date: "asc" }, select: { date: true } }).catch(() => null),
      prisma.metricSnapshot.findFirst({ where: { brandId: brand.id }, orderBy: { date: "desc" }, select: { date: true } }).catch(() => null),
    ]);

    const conv = agg._sum.conversions ?? 0;
    const sess = agg._sum.sessions ?? 0;
    let status: "healthy" | "suspicious" | "corrupted" = "healthy";
    if (sess > 0 && conv > sess) status = "suspicious";
    if (sess > 0 && conv > sess * 5) status = "corrupted";

    rows.push({
      brandId: brand.id, name: brand.name, domain: brand.domain,
      totalSnapshots: count,
      dateRange: first?.date && last?.date
        ? `${first.date.toISOString().slice(0, 10)} — ${last.date.toISOString().slice(0, 10)}`
        : "—",
      totalConversions: conv, totalSessions: sess, status,
    });
  }

  return NextResponse.json({ brands: rows });
}

// ─── GA4 Purge ─────────────────────────────────────────────────────────────

async function ga4Purge(brandId: string) {
  if (!brandId) return NextResponse.json({ error: "brandId required" }, { status: 400 });

  const deleted = await prisma.metricSnapshot.deleteMany({
    where: {
      brandId,
      source: "ga4",
      conversions: { gt: 0 },
      sessions: { gt: 0 },
    },
  }).catch(() => ({ count: 0 }));

  // Only delete rows where conversions > sessions * 5, but Prisma
  // doesn't support cross-column comparisons in where. Use raw SQL.
  const purged = await prisma.$executeRaw`
    DELETE FROM "MetricSnapshot"
    WHERE "brandId" = ${brandId}
      AND "source" = 'ga4'
      AND "conversions" > "sessions" * 5
  `.catch(() => 0);

  return NextResponse.json({ purged, brandId });
}

// ─── Fill Queries ──────────────────────────────────────────────────────────

async function fillQueries() {
  const nullCount = await prisma.aiAttribution.count({ where: { queryContext: null } }).catch(() => 0);
  const patched = await backfillMissingQueryContext().catch(() => 0);
  return NextResponse.json({ nullBefore: nullCount, patched });
}

// ─── Cron Status ───────────────────────────────────────────────────────────

async function cronStatus() {
  const crons = [
    { route: "/api/cron/refresh-tokens", schedule: "*/45 * * * *" },
    { route: "/api/cron/integration-sync", schedule: "0 5 * * *" },
    { route: "/api/cron/platform-snapshot", schedule: "0 2 * * *" },
    { route: "/api/cron/rank-check", schedule: "0 6 * * *" },
    { route: "/api/cron/signal-detection", schedule: "0 */6 * * *" },
    { route: "/api/cron/signals-site-tag-ai", schedule: "0 */4 * * *" },
    { route: "/api/cron/signals-competitor-regional", schedule: "0 */6 * * *" },
    { route: "/api/cron/data-retention", schedule: "0 3 * * *" },
    { route: "/api/cron/brand-sitemap-crawl", schedule: "0 4 * * *" },
    { route: "/api/cron/check-alerts", schedule: "0 */3 * * *" },
    { route: "/api/cron/competitor-crawl", schedule: "0 7 * * *" },
    { route: "/api/cron/compute-benchmarks", schedule: "0 8 * * 0" },
    { route: "/api/cron/email-reports", schedule: "0 9 * * 1" },
    { route: "/api/cron/track-outcomes", schedule: "0 10 * * *" },
    { route: "/api/cron/paid-media-rebuild", schedule: "0 3 * * *" },
    { route: "/api/cron/industry-intel", schedule: "0 11 * * 1" },
    { route: "/api/cron/ai-visibility", schedule: "0 12 * * *" },
    { route: "/api/cron/backlink-sync", schedule: "0 8 * * *" },
    { route: "/api/cron/gbp-sync", schedule: "0 6 * * *" },
    { route: "/api/cron/ai-citation-check", schedule: "0 9 * * 1" },
    { route: "/api/cron/ai-strategy-recommendations", schedule: "0 11 * * *" },
  ];

  const logs = await prisma.cronLog.findMany({
    orderBy: { startedAt: "desc" },
    take: 100,
  }).catch(() => []);

  const lastByRoute = new Map<string, typeof logs[0]>();
  for (const log of logs) {
    if (!lastByRoute.has(log.route)) lastByRoute.set(log.route, log);
  }

  return NextResponse.json({
    crons: crons.map((c) => {
      const last = lastByRoute.get(c.route);
      return {
        route: c.route,
        schedule: c.schedule,
        lastRun: last?.startedAt?.toISOString() ?? null,
        lastStatus: last?.status ?? "never",
        lastDuration: last?.duration ?? null,
        lastDetails: last?.details ?? null,
      };
    }),
  });
}

// ─── Trigger Cron ──────────────────────────────────────────────────────────

async function triggerCron(route: string, req: Request) {
  if (!route) return NextResponse.json({ error: "route required" }, { status: 400 });
  const cronSecret = process.env.CRON_SECRET;
  const origin = new URL(req.url).origin;
  const res = await fetch(`${origin}${route}`, {
    method: "GET",
    headers: cronSecret ? { authorization: `Bearer ${cronSecret}` } : {},
  }).catch((err) => ({ ok: false, status: 0, json: async () => ({ error: err.message }) }));
  const body = await (res as Response).json?.().catch(() => ({}));
  return NextResponse.json({ ok: (res as Response).ok ?? false, status: (res as Response).status ?? 0, body });
}

// ─── Table Sizes ───────────────────────────────────────────────────────────

async function tableSizes() {
  type Row = { relname: string; n_live_tup: bigint };
  const rows = await prisma.$queryRaw<Row[]>`
    SELECT relname, n_live_tup
    FROM pg_stat_user_tables
    ORDER BY n_live_tup DESC
    LIMIT 30
  `.catch(() => []);

  return NextResponse.json({
    tables: rows.map((r) => ({
      name: r.relname,
      rows: Number(r.n_live_tup),
    })),
  });
}

// ─── Site Tag Health ───────────────────────────────────────────────────────

async function siteTagHealth() {
  const sites = await prisma.trackedSite.findMany({
    select: {
      id: true,
      brandId: true,
      lastEventAt: true,
      brand: { select: { name: true, domain: true } },
    },
  });

  const now = Date.now();
  const rows = sites.map((s) => {
    const lastMs = s.lastEventAt ? s.lastEventAt.getTime() : 0;
    const hoursSince = lastMs > 0 ? (now - lastMs) / 3_600_000 : Infinity;
    const status = hoursSince < 1 ? "active" : hoursSince < 6 ? "slow" : "down";
    return {
      brandId: s.brandId,
      name: s.brand.name,
      domain: s.brand.domain,
      lastEventAt: s.lastEventAt?.toISOString() ?? null,
      status,
      hoursSinceLastEvent: Math.round(hoursSince * 10) / 10,
    };
  });

  return NextResponse.json({ sites: rows.sort((a, b) => a.hoursSinceLastEvent - b.hoursSinceLastEvent) });
}

// ─── Brand Status ──────────────────────────────────────────────────────────

async function brandStatus() {
  const brands = await prisma.brand.findMany({
    select: {
      id: true, name: true, domain: true, plan: true, status: true,
      createdAt: true,
      organization: { select: { name: true } },
      trackedSite: { select: { lastEventAt: true } },
    },
    orderBy: { createdAt: "desc" },
  });

  return NextResponse.json({
    brands: brands.map((b) => ({
      id: b.id,
      name: b.name,
      domain: b.domain,
      organization: b.organization.name,
      plan: b.plan,
      status: b.status,
      createdAt: b.createdAt.toISOString(),
      lastActivity: b.trackedSite?.lastEventAt?.toISOString() ?? null,
    })),
  });
}

// ─── Test AI Referral ──────────────────────────────────────────────────────

async function testAiReferral(body: Record<string, unknown>) {
  const { brandId, platform, landingPage, queryContext } = body as {
    brandId?: string; platform?: string; landingPage?: string; queryContext?: string;
  };
  if (!brandId || !platform || !landingPage) {
    return NextResponse.json({ error: "brandId, platform, landingPage required" }, { status: 400 });
  }

  const record = await prisma.aiAttribution.create({
    data: {
      brandId,
      sessionId: `test_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`,
      channel: platform === "google_ai_overview" ? "geo" : "llmo",
      aiPlatform: platform,
      referrerUrl: `https://${platform}.test/demo`,
      queryContext: queryContext || `[test] ${landingPage.replace(/\//g, " ").trim()}`,
      landingPage,
    },
  });

  return NextResponse.json({ ok: true, id: record.id });
}

// ─── Error Log ─────────────────────────────────────────────────────────────

async function errorLog() {
  const logs = await prisma.errorLog.findMany({
    orderBy: { createdAt: "desc" },
    take: 100,
  }).catch(() => []);

  return NextResponse.json({ errors: logs });
}

async function clearErrors() {
  const cutoff = new Date(Date.now() - 7 * 86_400_000);
  const deleted = await prisma.errorLog.deleteMany({
    where: { createdAt: { lt: cutoff } },
  }).catch(() => ({ count: 0 }));
  return NextResponse.json({ deleted: deleted.count });
}

async function sourceFreshness() {
  const brands = await prisma.brand.findMany({
    where: { status: { not: "deleted" } },
    select: { id: true, name: true, domain: true },
  });

  const rows = await Promise.all(
    brands.map(async (b) => {
      const f = await getSourceFreshness(b.id);
      return {
        brandId: b.id,
        name: b.name,
        domain: b.domain,
        ga4: f.ga4,
        gsc: f.gsc,
        siteTag: f.siteTag,
        dataforseo: f.dataforseo,
      };
    })
  );

  return NextResponse.json({ brands: rows });
}
