import { NextRequest, NextResponse } from "next/server";
import { db, isDatabaseAvailable } from "@/lib/db";
import { ensureDatabaseInitialized } from "@/lib/db/init";
import { getAdminUser } from "@/lib/auth/admin";
import { clientIp } from "@/lib/auth/rateLimit";
import {
  logSecurityEventAsync,
  SecurityEventType,
} from "@/lib/auth/securityEvents";
import { and, count, eq, gte, sql } from "drizzle-orm";
import { guest_sessions, receipts, sessions, users, waitlist } from "@/lib/schema/db";

export const runtime = "nodejs";

const DAYS = (n: number) => new Date(Date.now() - n * 24 * 60 * 60 * 1000);
const REGISTERED = eq(users.isGuest, false);

export async function GET(req: NextRequest) {
  const admin = await getAdminUser();
  if (!admin) return NextResponse.json({ error: 'Forbidden' }, { status: 403 });

  logSecurityEventAsync({
    type: SecurityEventType.ADMIN_ACTION,
    userId: admin.id,
    email: admin.email,
    ip: clientIp(req),
    userAgent: req.headers.get("user-agent"),
    metadata: { route: "/api/admin/stats", method: "GET" },
  });

  if (!(await isDatabaseAvailable())) {
    return NextResponse.json({ error: 'Database unavailable' }, { status: 503 });
  }
  await ensureDatabaseInitialized();

  try {
    const [
      total,
      free,
      weekly,
      annual,
      lifetime,
      newToday,
      new7d,
      new30d,
      totalScans,
      totalReceipts,
      waitlistCount,
      activeSessions,
      guestSessions,
      onboardingCompleted,
    ] = await Promise.all([
      db.select({ value: count() }).from(users).where(REGISTERED),
      db.select({ value: count() }).from(users).where(and(REGISTERED, eq(users.plan, "free"))),
      db.select({ value: count() }).from(users).where(and(REGISTERED, eq(users.plan, "weekly"))),
      db.select({ value: count() }).from(users).where(and(REGISTERED, eq(users.plan, "annual"))),
      db.select({ value: count() }).from(users).where(and(REGISTERED, eq(users.plan, "lifetime"))),
      db.select({ value: count() }).from(users).where(and(REGISTERED, gte(users.createdAt, DAYS(1)))),
      db.select({ value: count() }).from(users).where(and(REGISTERED, gte(users.createdAt, DAYS(7)))),
      db.select({ value: count() }).from(users).where(and(REGISTERED, gte(users.createdAt, DAYS(30)))),
      db.select({ value: sql<string>`COALESCE(SUM(${users.scanCount}), 0)` }).from(users),
      db.select({ value: count() }).from(receipts),
      db.select({ value: count() }).from(waitlist),
      db.select({ value: count() }).from(sessions).where(gte(sessions.expiresAt, new Date())),
      db.select({ value: count() }).from(guest_sessions),
      db.select({ value: count() }).from(users).where(and(REGISTERED, sql`${users.onboardingCompletedAt} IS NOT NULL`)),
    ]);

    const totalUsers = Number(total[0]?.value ?? 0);
    const guestSessionsCount = Number(guestSessions[0]?.value ?? 0);
    const totalUsersCount = totalUsers + guestSessionsCount;
    const conversionRate = totalUsersCount > 0 ? (totalUsers / totalUsersCount) * 100 : 0;

    const [dailySignups, dailyScans, personas, volumes, exports, referrals] = await Promise.all([
      db
        .select({
          date: sql<string>`DATE(${users.createdAt})`,
          count: count(),
        })
        .from(users)
        .where(and(REGISTERED, gte(users.createdAt, DAYS(30))))
        .groupBy(sql`DATE(${users.createdAt})`)
        .orderBy(sql`DATE(${users.createdAt}) ASC`),
      db
        .select({
          date: sql<string>`DATE(${receipts.createdAt})`,
          count: count(),
        })
        .from(receipts)
        .where(gte(receipts.createdAt, DAYS(30)))
        .groupBy(sql`DATE(${receipts.createdAt})`)
        .orderBy(sql`DATE(${receipts.createdAt}) ASC`),
      db
        .select({
          useCase: sql<string>`COALESCE(${users.useCase}, 'unassigned')`,
          count: count(),
        })
        .from(users)
        .where(REGISTERED)
        .groupBy(sql`COALESCE(${users.useCase}, 'unassigned')`),
      db
        .select({
          volume: sql<string>`COALESCE(${users.monthlyVolume}, 'unassigned')`,
          count: count(),
        })
        .from(users)
        .where(REGISTERED)
        .groupBy(sql`COALESCE(${users.monthlyVolume}, 'unassigned')`),
      db
        .select({
          format: sql<string>`COALESCE(${users.exportFormat}, 'unassigned')`,
          count: count(),
        })
        .from(users)
        .where(REGISTERED)
        .groupBy(sql`COALESCE(${users.exportFormat}, 'unassigned')`),
      db
        .select({
          source: sql<string>`COALESCE(${users.referralSource}, 'unassigned')`,
          count: count(),
        })
        .from(users)
        .where(REGISTERED)
        .groupBy(sql`COALESCE(${users.referralSource}, 'unassigned')`),
    ]);

    return NextResponse.json({
      users: {
        total: totalUsers,
        free: Number(free[0]?.value ?? 0),
        proWeekly: Number(weekly[0]?.value ?? 0),
        proAnnual: Number(annual[0]?.value ?? 0),
        proLifetime: Number(lifetime[0]?.value ?? 0),
        waitlist: Number(waitlistCount[0]?.value ?? 0),
        newToday: Number(newToday[0]?.value ?? 0),
        new7d: Number(new7d[0]?.value ?? 0),
        new30d: Number(new30d[0]?.value ?? 0),
      },
      activity: {
        totalScans: Number(totalScans[0]?.value ?? 0),
        activeSessions: Number(activeSessions[0]?.value ?? 0),
        conversionRate,
      },
      growth: {
        users: dailySignups.map((r) => ({ date: String(r.date), count: Number(r.count) })),
        scans: dailyScans.map((r) => ({ date: String(r.date), count: Number(r.count) })),
      },
      onboarding: {
        completedCount: Number(onboardingCompleted[0]?.value ?? 0),
        personas: personas.map((p) => ({ key: p.useCase, count: Number(p.count) })),
        volumes: volumes.map((v) => ({ key: v.volume, count: Number(v.count) })),
        exportFormats: exports.map((e) => ({ key: e.format, count: Number(e.count) })),
        referrals: referrals.map((r) => ({ key: r.source, count: Number(r.count) })),
      },
    });
  } catch (error) {
    console.error("Admin stats error:", error);
    return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
  }
}