import { NextRequest, NextResponse } from "next/server";
import { getEventsForDate, getNarrative, upsertNarrative } from "@/lib/chronicle-db";

const CHANNEL_URL = process.env.CHANNEL_URL || "http://127.0.0.1:7100";
const CHANNEL_SECRET = process.env.CHANNEL_SECRET || "";

export async function GET(
  _request: NextRequest,
  { params }: { params: Promise<{ date: string }> }
) {
  try {
    const { date } = await params;
    const cached = getNarrative(date);
    if (cached) {
      return NextResponse.json({ date, narrative: cached.narrative, generatedAt: cached.generatedAt });
    }
    return NextResponse.json({ date, narrative: null });
  } catch (err) {
    console.error("[chronicle/narrative GET]", err);
    return NextResponse.json({ error: "Failed to fetch narrative" }, { status: 500 });
  }
}

export async function POST(
  _request: NextRequest,
  { params }: { params: Promise<{ date: string }> }
) {
  try {
    const { date } = await params;

    const events = getEventsForDate(date);
    if (events.length === 0) {
      return NextResponse.json({ error: "No events for this date" }, { status: 404 });
    }

    // Build a structured summary to send to the agent
    const formattedDate = new Date(date + "T12:00:00").toLocaleDateString("en-US", {
      weekday: "long",
      year: "numeric",
      month: "long",
      day: "numeric",
    });

    const eventLines = events.map((e) => {
      const time = new Date(e.timestamp).toLocaleTimeString("en-US", {
        hour: "numeric",
        minute: "2-digit",
        hour12: true,
      });
      return `- [${e.source.toUpperCase()}] ${time}: ${e.title}${e.body ? ` — ${e.body}` : ""}`;
    });

    const prompt = [
      `You are the Teletraan Chronicle narrator. Write a warm, personal 2-3 sentence narrative summary of ${formattedDate} based on the following captured events. `,
      `Make it feel like a diary entry — concise, observational, with personality. Focus on patterns, mood, and what mattered most.`,
      ``,
      `Events:`,
      ...eventLines,
      ``,
      `Write only the 2-3 sentence narrative. No intro, no labels, no bullet points.`,
    ].join("\n");

    // Send to agent and collect the streamed reply
    const narrative = await generateNarrativeFromAgent(prompt);
    upsertNarrative(date, narrative);

    return NextResponse.json({ date, narrative, generatedAt: Date.now() });
  } catch (err) {
    console.error("[chronicle/narrative POST]", err);
    return NextResponse.json({ error: "Narrative generation failed" }, { status: 500 });
  }
}

async function generateNarrativeFromAgent(prompt: string): Promise<string> {
  // 1. Send message to agent
  const sendRes = await fetch(`${CHANNEL_URL}/message`, {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: `Bearer ${CHANNEL_SECRET}`,
    },
    body: JSON.stringify({
      text: prompt,
      user_email: "chronicle@teletraan.internal",
    }),
  });

  if (!sendRes.ok) {
    throw new Error(`Channel server error on send: ${sendRes.status}`);
  }

  const { conversation_id } = await sendRes.json() as { conversation_id: string };

  // 2. Consume the SSE stream until we get the full reply
  const streamRes = await fetch(
    `${CHANNEL_URL}/stream?conversation_id=${encodeURIComponent(conversation_id)}`,
    {
      headers: { Authorization: `Bearer ${CHANNEL_SECRET}` },
      signal: AbortSignal.timeout(60_000),
    }
  );

  if (!streamRes.ok || !streamRes.body) {
    throw new Error(`Stream error: ${streamRes.status}`);
  }

  let accumulated = "";
  const reader = streamRes.body.getReader();
  const decoder = new TextDecoder();
  let buffer = "";

  while (true) {
    const { done, value } = await reader.read();
    if (done) break;

    buffer += decoder.decode(value, { stream: true });
    const lines = buffer.split("\n");
    buffer = lines.pop() ?? "";

    for (const line of lines) {
      if (!line.startsWith("data: ")) continue;
      const json = line.slice(6).trim();
      if (!json || json === "[DONE]") continue;

      try {
        const msg = JSON.parse(json) as { type: string; text?: string; status?: string };
        if (msg.type === "reply" && msg.text) {
          accumulated += msg.text;
        }
        // Stop when agent is done
        if (msg.type === "status" && msg.status === "idle" && accumulated.length > 0) {
          reader.cancel();
          return accumulated.trim();
        }
      } catch {
        // Ignore parse errors on individual SSE events
      }
    }
  }

  if (!accumulated) {
    throw new Error("No reply received from agent");
  }

  return accumulated.trim();
}
