import { NextRequest, NextResponse } from "next/server";
import { auth } from "@/lib/auth";
import { db } from "@/lib/db";
import { logger } from "@/lib/logger";
import { runResearch } from "@/lib/token/agents/researcher";
import { buildSystemPrompt } from "@/lib/token/system-prompt";

const CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours

function normalizeQuery(q: string): string {
  return q
    .trim()
    .toLowerCase()
    .replace(/[^a-z0-9\s]/g, "")
    .replace(/\s+/g, " ");
}

/**
 * POST /api/token/research — Run a dedicated research query.
 *
 * Body: { query: string, conversationId?: string }
 * Returns: { result: ResearchResult, conversationId: string, cached: boolean }
 */
export async function POST(req: NextRequest) {
  const session = await auth();
  if (!session?.user?.id) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  try {
    const body = await req.json();
    const { query, conversationId } = body;

    if (!query || typeof query !== "string" || query.trim().length === 0) {
      return NextResponse.json({ error: "query is required" }, { status: 400 });
    }

    // Load config
    let config = await db.tokenConfig.findUnique({ where: { id: "singleton" } });
    if (!config) {
      config = await db.tokenConfig.create({ data: { id: "singleton" } });
    }

    if (!config.enabled) {
      return NextResponse.json({ error: "Token is disabled" }, { status: 503 });
    }

    if (config.totalSpentUsd >= config.monthlyBudgetUsd) {
      return NextResponse.json({ error: "Monthly budget exceeded" }, { status: 429 });
    }

    // Check cache — look for recent research messages with similar queries
    const cacheHit = await db.tokenMessage.findFirst({
      where: {
        messageType: "research",
        role: "assistant",
        content: { not: "" },
        createdAt: { gte: new Date(Date.now() - CACHE_TTL_MS) },
        conversation: { userId: session.user.id },
      },
      orderBy: { createdAt: "desc" },
      include: {
        conversation: {
          include: {
            messages: {
              where: { role: "user" },
              orderBy: { createdAt: "desc" },
              take: 1,
            },
          },
        },
      },
    });

    // Simple cache: if the most recent research had a user message matching this query
    if (cacheHit) {
      const lastUserMsg = cacheHit.conversation.messages[0];
      if (lastUserMsg && normalizeQuery(lastUserMsg.content) === normalizeQuery(query)) {
        logger.info({ action: "token_research_cache_hit" }, "Research cache hit");
        return NextResponse.json({
          result: {
            content: cacheHit.content,
            model: cacheHit.model ?? config.researchModel,
            inputTokens: cacheHit.inputTokens,
            outputTokens: cacheHit.outputTokens,
            costUsd: 0,
            latencyMs: 0,
          },
          conversationId: cacheHit.conversationId,
          cached: true,
        });
      }
    }

    // Build fleet context
    const user = await db.user.findUnique({
      where: { id: session.user.id },
      select: { name: true, plan: true },
    });

    const devices = await db.device.findMany({
      where: { userId: session.user.id },
      orderBy: { lastSeen: "desc" },
    });

    const fleetContext = buildSystemPrompt({
      userName: user?.name ?? "Unknown",
      plan: user?.plan ?? "free",
      devices: devices.map((d) => ({
        name: d.name,
        status: d.status,
        models: JSON.parse(d.models) as string[],
        hardware: d.hardware,
        tunnelUrl: d.tunnelUrl,
      })),
    });

    // Get or create conversation
    let convId = conversationId as string | undefined;
    if (!convId) {
      const title = `Research: ${query.trim().slice(0, 60)}${query.length > 60 ? "..." : ""}`;
      const conv = await db.tokenConversation.create({
        data: { userId: session.user.id, title },
      });
      convId = conv.id;
    }

    // Save user query as message
    await db.tokenMessage.create({
      data: {
        conversationId: convId,
        role: "user",
        content: query.trim(),
      },
    });

    // Run research
    const result = await runResearch({
      query: query.trim(),
      model: config.researchModel,
      fleetContext,
      temperature: 0.3,
      maxTokens: 8192,
    });

    // Save research result
    await db.tokenMessage.create({
      data: {
        conversationId: convId,
        role: "assistant",
        content: result.content,
        model: result.model,
        inputTokens: result.inputTokens,
        outputTokens: result.outputTokens,
        costUsd: result.costUsd,
        latencyMs: result.latencyMs,
        messageType: "research",
      },
    });

    // Update spending
    await db.tokenConfig.update({
      where: { id: "singleton" },
      data: { totalSpentUsd: { increment: result.costUsd } },
    });

    logger.info(
      {
        action: "token_research",
        conversation_id: convId,
        model: result.model,
        cost_usd: result.costUsd,
      },
      "Research query completed",
    );

    return NextResponse.json({
      result,
      conversationId: convId,
      cached: false,
    });
  } catch (err) {
    logger.error({ err, action: "token_research_error" }, "Research failed");
    return NextResponse.json(
      { error: "Research failed. Please try again." },
      { status: 500 },
    );
  }
}
