/**
 * GET  /api/projects/[projectId]/agent/sessions/[sessionId]/events?afterSeq=0
 *   List persisted agent events for replay (user session auth).
 *
 * POST /api/projects/[projectId]/agent/sessions/[sessionId]/events
 *   Batch append from vibn-agent-runner (x-agent-runner-secret).
 */
import { NextResponse } from "next/server";
import { authSession } from "@/lib/auth/session-server";
import { query, getPool } from "@/lib/db-postgres";

export interface AgentSessionEventRow {
  seq: number;
  ts: string;
  type: string;
  payload: Record<string, unknown>;
}

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

    const afterSeq = Math.max(0, parseInt(new URL(req.url).searchParams.get("afterSeq") ?? "0", 10) || 0);

    const rows = await query<AgentSessionEventRow>(
      `SELECT e.seq, e.ts::text, e.type, e.payload
       FROM agent_session_events e
       JOIN agent_sessions s ON s.id = e.session_id
       JOIN fs_projects p ON p.id::text = s.project_id::text
       JOIN fs_users u ON u.id = p.user_id
       WHERE e.session_id = $1::uuid AND s.project_id::text = $2 AND u.data->>'email' = $3
         AND e.seq > $4
       ORDER BY e.seq ASC
       LIMIT 2000`,
      [sessionId, projectId, session.user.email, afterSeq]
    );

    const maxSeq = rows.length ? rows[rows.length - 1].seq : afterSeq;

    return NextResponse.json({ events: rows, maxSeq });
  } catch (err) {
    console.error("[agent/sessions/.../events GET]", err);
    return NextResponse.json({ error: "Failed to list events" }, { status: 500 });
  }
}

type IngestBody = {
  events: Array<{
    clientEventId: string;
    ts: string;
    type: string;
    payload?: Record<string, unknown>;
  }>;
};

export async function POST(
  req: Request,
  { params }: { params: Promise<{ projectId: string; sessionId: string }> }
) {
  const secret = process.env.AGENT_RUNNER_SECRET ?? "";
  const incomingSecret = req.headers.get("x-agent-runner-secret") ?? "";
  if (secret && incomingSecret !== secret) {
    return NextResponse.json({ error: "Forbidden" }, { status: 403 });
  }

  const { projectId, sessionId } = await params;

  let body: IngestBody;
  try {
    body = (await req.json()) as IngestBody;
  } catch {
    return NextResponse.json({ error: "Invalid JSON" }, { status: 400 });
  }

  if (!body.events?.length) {
    return NextResponse.json({ ok: true, inserted: 0 });
  }

  const pool = getPool();
  const client = await pool.connect();

  try {
    const exists = await client.query<{ n: string }>(
      `SELECT 1 AS n FROM agent_sessions WHERE id = $1::uuid AND project_id::text = $2 LIMIT 1`,
      [sessionId, projectId]
    );
    if (exists.rowCount === 0) {
      return NextResponse.json({ error: "Session not found" }, { status: 404 });
    }

    await client.query("BEGIN");
    await client.query("SELECT pg_advisory_xact_lock(hashtext($1::text))", [sessionId]);

    let inserted = 0;
    for (const ev of body.events) {
      if (!ev.clientEventId || !ev.type || !ev.ts) continue;

      const maxRes = await client.query<{ m: string }>(
        `SELECT COALESCE(MAX(seq), 0)::text AS m FROM agent_session_events WHERE session_id = $1::uuid`,
        [sessionId]
      );
      const nextSeq = Number(maxRes.rows[0].m) + 1;

      const ins = await client.query(
        `INSERT INTO agent_session_events (session_id, project_id, seq, ts, type, payload, client_event_id)
         VALUES ($1::uuid, $2, $3, $4::timestamptz, $5, $6::jsonb, $7::uuid)
         ON CONFLICT (client_event_id) DO NOTHING`,
        [
          sessionId,
          projectId,
          nextSeq,
          ev.ts,
          ev.type,
          JSON.stringify(ev.payload ?? {}),
          ev.clientEventId,
        ]
      );
      if (ins.rowCount) inserted += ins.rowCount;
    }

    await client.query("COMMIT");
    return NextResponse.json({ ok: true, inserted });
  } catch (err) {
    try {
      await client.query("ROLLBACK");
    } catch {
      /* ignore */
    }
    console.error("[agent/sessions/.../events POST]", err);
    return NextResponse.json({ error: "Failed to ingest events" }, { status: 500 });
  } finally {
    client.release();
  }
}
