import { NextRequest, NextResponse } from "next/server";
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/lib/auth/authOptions";
import { query } from "@/lib/db-postgres";

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

// ---------------------------------------------------------------------------
// DB helpers — atlas_conversations table
// ---------------------------------------------------------------------------

let tableReady = false;

async function ensureTable() {
  if (tableReady) return;
  await query(`
    CREATE TABLE IF NOT EXISTS atlas_conversations (
      project_id TEXT PRIMARY KEY,
      messages   JSONB NOT NULL DEFAULT '[]'::jsonb,
      updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
    )
  `);
  tableReady = true;
}

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

async function saveAtlasHistory(projectId: string, messages: any[]): Promise<void> {
  try {
    await ensureTable();
    await query(
      `INSERT INTO atlas_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("[atlas-chat] Failed to save history:", e);
  }
}

async function savePrd(projectId: string, prdContent: string): Promise<void> {
  try {
    await query(
      `UPDATE fs_projects
         SET data = data || jsonb_build_object('prd', $2::text, 'stage', 'architecture'),
             updated_at = NOW()
       WHERE id = $1`,
      [projectId, prdContent]
    );
    console.log(`[atlas-chat] PRD saved for project ${projectId}`);
  } catch (e) {
    console.error("[atlas-chat] Failed to save PRD:", e);
  }
}

// ---------------------------------------------------------------------------
// GET — load stored conversation messages for display
// ---------------------------------------------------------------------------

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

  const { projectId } = await params;
  const history = await loadAtlasHistory(projectId);

  // Filter to only user/assistant messages (no system prompts) for display
  const messages = history
    .filter((m: any) => m.role === "user" || m.role === "assistant")
    .map((m: any) => ({ role: m.role as "user" | "assistant", content: m.content as string }));

  return NextResponse.json({ messages });
}

// ---------------------------------------------------------------------------
// POST — send message to Atlas
// ---------------------------------------------------------------------------

export async function POST(
  req: NextRequest,
  { params }: { params: Promise<{ projectId: string }> }
) {
  const session = await getServerSession(authOptions);
  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 });
  }

  const sessionId = `atlas_${projectId}`;

  // Load conversation history from DB to persist across agent runner restarts.
  // Strip tool_call / tool_response messages — replaying them across sessions
  // causes Gemini to reject the request with a turn-ordering error.
  const rawHistory = await loadAtlasHistory(projectId);
  const history = rawHistory.filter((m: any) =>
    (m.role === "user" || m.role === "assistant") && m.content
  );

  // __init__ is a special internal trigger used only when there is no existing history.
  // If history already exists, ignore the init request (conversation already started).
  const isInit = message.trim() === "__atlas_init__";
  if (isInit && history.length > 0) {
    return NextResponse.json({ reply: null, alreadyStarted: true });
  }

  try {
    const res = await fetch(`${AGENT_RUNNER_URL}/atlas/chat`, {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({
        // For init, send the greeting prompt but don't store it as a user message
        message: isInit
          ? "Begin the conversation. Introduce yourself as Atlas and ask what the user is building. Do not acknowledge this as an internal trigger."
          : message,
        session_id: sessionId,
        history,
        is_init: isInit,
      }),
      signal: AbortSignal.timeout(120_000),
    });

    if (!res.ok) {
      const text = await res.text();
      console.error("[atlas-chat] Agent runner error:", text);
      return NextResponse.json(
        { error: "Atlas is unavailable. Please try again." },
        { status: 502 }
      );
    }

    const data = await res.json();

    // Persist updated history
    await saveAtlasHistory(projectId, data.history ?? []);

    // If Atlas finalized the PRD, save it to the project
    if (data.prdContent) {
      await savePrd(projectId, data.prdContent);
    }

    return NextResponse.json({
      reply: data.reply,
      sessionId,
      prdContent: data.prdContent ?? null,
      model: data.model ?? null,
    });
  } catch (err) {
    console.error("[atlas-chat] Error:", err);
    return NextResponse.json(
      { error: "Request timed out or failed. Please try again." },
      { status: 500 }
    );
  }
}

// ---------------------------------------------------------------------------
// DELETE — clear Atlas conversation for this project
// ---------------------------------------------------------------------------

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

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

  try {
    await fetch(`${AGENT_RUNNER_URL}/atlas/sessions/${sessionId}`, { method: "DELETE" });
  } catch { /* runner may be down */ }

  try {
    await query(`DELETE FROM atlas_conversations WHERE project_id = $1`, [projectId]);
  } catch { /* table may not exist yet */ }

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