import { NextRequest, NextResponse } from "next/server";
import { authSession } from "@/lib/auth/session-server";
import { query } from "@/lib/db-postgres";
import { formatCreationKickoffForPrompt } from "@/lib/server/creation-kickoff-prompt";

const AGENT_RUNNER_URL = process.env.AGENT_RUNNER_URL ?? "http://localhost:3333";

// ---------------------------------------------------------------------------
// Helpers — chat_conversations + fs_knowledge_items
// ---------------------------------------------------------------------------

async function loadConversation(projectId: string): Promise<any[]> {
  try {
    const rows = await query<{ messages: any[] }>(
      `SELECT messages FROM chat_conversations WHERE project_id = $1`,
      [projectId]
    );
    return rows[0]?.messages ?? [];
  } catch {
    return [];
  }
}

async function saveConversation(projectId: string, messages: any[]): Promise<void> {
  try {
    await query(
      `INSERT INTO chat_conversations (project_id, messages, updated_at)
       VALUES ($1, $2::jsonb, NOW())
       ON CONFLICT (project_id) DO UPDATE
         SET messages = $2::jsonb, updated_at = NOW()`,
      [projectId, JSON.stringify(messages)]
    );
  } catch (e) {
    console.error("[agent-chat] Failed to save conversation:", e);
  }
}

async function loadKnowledge(projectId: string): Promise<string> {
  try {
    const rows = await query<{ data: any }>(
      `SELECT data FROM fs_knowledge_items WHERE project_id = $1 ORDER BY updated_at DESC LIMIT 50`,
      [projectId]
    );
    if (rows.length === 0) return "";
    return rows
      .map((r) => `[${r.data.type ?? "note"}] ${r.data.key}: ${r.data.value}`)
      .join("\n");
  } catch {
    return "";
  }
}

async function saveMemoryUpdates(
  projectId: string,
  updates: Array<{ key: string; type: string; value: string }>
): Promise<void> {
  if (!updates?.length) return;
  try {
    for (const u of updates) {
      // Upsert by project_id + key
      const existing = await query<{ id: string }>(
        `SELECT id FROM fs_knowledge_items WHERE project_id = $1 AND data->>'key' = $2 LIMIT 1`,
        [projectId, u.key]
      );
      if (existing.length > 0) {
        await query(
          `UPDATE fs_knowledge_items SET data = $1::jsonb, updated_at = NOW() WHERE id = $2`,
          [JSON.stringify({ key: u.key, type: u.type, value: u.value, source: "ai" }), existing[0].id]
        );
      } else {
        await query(
          `INSERT INTO fs_knowledge_items (project_id, data) VALUES ($1, $2::jsonb)`,
          [projectId, JSON.stringify({ key: u.key, type: u.type, value: u.value, source: "ai" })]
        );
      }
    }
  } catch (e) {
    console.error("[agent-chat] Failed to save memory updates:", e);
  }
}

// ---------------------------------------------------------------------------
// POST — send a message
// ---------------------------------------------------------------------------

export async function POST(
  req: NextRequest,
  { params }: { params: Promise<{ projectId: string }> }
) {
  const session = await authSession();
  if (!session?.user?.email) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const { projectId } = await params;
  const { message } = await req.json();

  if (!message?.trim()) {
    return NextResponse.json({ error: '"message" is required' }, { status: 400 });
  }

  // Load project context
  let projectContext = "";
  try {
    const rows = await query<{ data: any }>(
      `SELECT data FROM fs_projects WHERE id = $1 LIMIT 1`,
      [projectId]
    );
    if (rows.length > 0) {
      const p = rows[0].data;
      const lines = [
        `Project: ${p.productName ?? p.name ?? "Unnamed"}`,
        p.productVision ? `Vision: ${p.productVision}` : null,
        p.giteaRepo ? `Gitea repo: ${p.giteaRepo}` : null,
        p.coolifyAppUuid ? `Coolify app UUID: ${p.coolifyAppUuid}` : null,
        p.deploymentUrl ? `Live URL: ${p.deploymentUrl}` : null,
      ].filter(Boolean);
      const kickoffBlock = formatCreationKickoffForPrompt(p as Record<string, unknown>);
      if (kickoffBlock) lines.push("", kickoffBlock);
      projectContext = lines.join("\n");
    }
  } catch { /* non-fatal */ }

  const sessionId = `project_${projectId}`;

  // Load persistent conversation history and knowledge from DB
  const [history, knowledgeContext] = await Promise.all([
    loadConversation(projectId),
    loadKnowledge(projectId),
  ]);

  // Enrich user message with project context on the very first message
  const isFirstMessage = history.length === 0;
  const enrichedMessage =
    isFirstMessage && projectContext
      ? `[Project context]\n${projectContext}\n\n[User message]\n${message}`
      : message;

  try {
    const res = await fetch(`${AGENT_RUNNER_URL}/orchestrator/chat`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        message: enrichedMessage,
        session_id: sessionId,
        history,
        knowledge_context: knowledgeContext || undefined,
      }),
      signal: AbortSignal.timeout(120_000),
    });

    if (!res.ok) {
      const errText = await res.text();
      return NextResponse.json(
        { error: `Agent runner error: ${res.status} — ${errText.slice(0, 200)}` },
        { status: 502 }
      );
    }

    const data = await res.json();

    // Persist conversation and any memory updates the AI generated
    await Promise.all([
      saveConversation(projectId, data.history ?? []),
      saveMemoryUpdates(projectId, data.memoryUpdates ?? []),
    ]);

    return NextResponse.json({
      reply: data.reply,
      reasoning: data.reasoning ?? null,
      toolCalls: data.toolCalls ?? [],
      turns: data.turns ?? 0,
      model: data.model || null,
      sessionId,
      memoryUpdates: data.memoryUpdates ?? [],
    });
  } catch (err) {
    const msg = err instanceof Error ? err.message : String(err);
    return NextResponse.json(
      { error: msg.includes("fetch") ? "Agent runner is offline" : msg },
      { status: 503 }
    );
  }
}

// ---------------------------------------------------------------------------
// DELETE — clear session + conversation history
// ---------------------------------------------------------------------------

export async function DELETE(
  _req: NextRequest,
  { params }: { params: Promise<{ projectId: string }> }
) {
  const session = await authSession();
  if (!session?.user?.email) {
    return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
  }

  const { projectId } = await params;
  const sessionId = `project_${projectId}`;

  await Promise.all([
    // Clear in-memory session from agent runner
    fetch(`${AGENT_RUNNER_URL}/orchestrator/sessions/${sessionId}`, { method: "DELETE" }).catch(() => {}),
    // Clear persisted conversation from DB
    query(`DELETE FROM chat_conversations WHERE project_id = $1`, [projectId]).catch(() => {}),
  ]);

  return NextResponse.json({ cleared: true });
}
