import { readBody } from "h3";
import { createUIMessageStream, createUIMessageStreamResponse } from "ai";
import { getAuthContext } from "../utils/auth";
import { prisma } from "../utils/prisma";
import { buildChangeSet, captureSnapshot } from "../utils/changeSet";
import { persistChatMessage, runCrmAgentFor, type AgentTraceEvent } from "../agent/crmAgent";
import type { ChangeSet } from "../utils/changeSet";

function extractMessageText(message: any): string {
  if (!message || !Array.isArray(message.parts)) return "";
  return message.parts
    .filter((part: any) => part?.type === "text" && typeof part.text === "string")
    .map((part: any) => part.text)
    .join("")
    .trim();
}

function getLastUserText(messages: any[]): string {
  for (let i = messages.length - 1; i >= 0; i -= 1) {
    const message = messages[i];
    if (message?.role !== "user") continue;
    const text = extractMessageText(message);
    if (text) return text;
  }
  return "";
}

function humanizeTraceText(trace: AgentTraceEvent): string {
  if (trace.toolRun?.name) {
    return `Использую инструмент: ${trace.toolRun.name}`;
  }

  const text = (trace.text ?? "").trim();
  if (!text) return "Агент работает с данными CRM.";

  if (text.toLowerCase().includes("ошиб")) return "Возникла ошибка шага, пробую другой путь.";
  if (text.toLowerCase().includes("итог")) return "Готовлю финальный ответ.";
  return text;
}

function renderChangeSetSummary(changeSet: ChangeSet): string {
  const totals = { created: 0, updated: 0, deleted: 0 };
  for (const item of changeSet.items) {
    if (item.action === "created") totals.created += 1;
    else if (item.action === "updated") totals.updated += 1;
    else if (item.action === "deleted") totals.deleted += 1;
  }

  const byEntity = new Map<string, number>();
  for (const item of changeSet.items) {
    byEntity.set(item.entity, (byEntity.get(item.entity) ?? 0) + 1);
  }

  const lines = [
    "Technical change summary",
    `Total: ${changeSet.items.length} · Created: ${totals.created} · Updated: ${totals.updated} · Archived: ${totals.deleted}`,
    ...[...byEntity.entries()].map(([entity, count]) => `- ${entity}: ${count}`),
  ];

  return lines.join("\n");
}

export default defineEventHandler(async (event) => {
  const auth = await getAuthContext(event);
  const body = await readBody<{ messages?: any[] }>(event);
  const messages = Array.isArray(body?.messages) ? body.messages : [];
  const userText = getLastUserText(messages);

  if (!userText) {
    throw createError({ statusCode: 400, statusMessage: "Last user message is required" });
  }
  const requestId = `req_${Date.now()}_${Math.floor(Math.random() * 1_000_000)}`;

  const stream = createUIMessageStream({
    execute: async ({ writer }) => {
      const textId = `text-${Date.now()}`;
      writer.write({ type: "start" });
      try {
        const snapshotBefore = await captureSnapshot(prisma, auth.teamId);

        await persistChatMessage({
          teamId: auth.teamId,
          conversationId: auth.conversationId,
          authorUserId: auth.userId,
          role: "USER",
          text: userText,
          requestId,
          eventType: "user",
          phase: "final",
          transient: false,
        });

        const reply = await runCrmAgentFor({
          teamId: auth.teamId,
          userId: auth.userId,
          userText,
          requestId,
          conversationId: auth.conversationId,
          onTrace: async (trace: AgentTraceEvent) => {
            writer.write({
              type: "data-agent-log",
              data: {
                requestId,
                at: new Date().toISOString(),
                text: humanizeTraceText(trace),
              },
            });
          },
        });

        const snapshotAfter = await captureSnapshot(prisma, auth.teamId);
        const changeSet = buildChangeSet(snapshotBefore, snapshotAfter);

        await persistChatMessage({
          teamId: auth.teamId,
          conversationId: auth.conversationId,
          authorUserId: null,
          role: "ASSISTANT",
          text: reply.text,
          requestId,
          eventType: "assistant",
          phase: "final",
          transient: false,
        });

        if (changeSet) {
          await persistChatMessage({
            teamId: auth.teamId,
            conversationId: auth.conversationId,
            authorUserId: null,
            role: "ASSISTANT",
            text: renderChangeSetSummary(changeSet),
            requestId,
            eventType: "note",
            phase: "final",
            transient: false,
            messageKind: "change_set_summary",
            changeSet,
          });
        }

        writer.write({ type: "text-start", id: textId });
        writer.write({ type: "text-delta", id: textId, delta: reply.text });
        writer.write({ type: "text-end", id: textId });
        writer.write({ type: "finish", finishReason: "stop" });
      } catch (error: any) {
        const errorText = String(error?.message ?? error);

        await persistChatMessage({
          teamId: auth.teamId,
          conversationId: auth.conversationId,
          authorUserId: null,
          role: "ASSISTANT",
          text: errorText,
          requestId,
          eventType: "assistant",
          phase: "error",
          transient: false,
        });

        writer.write({
          type: "data-agent-log",
          data: {
            requestId,
            at: new Date().toISOString(),
            text: "Ошибка выполнения агентского цикла.",
          },
        });
        writer.write({ type: "text-start", id: textId });
        writer.write({
          type: "text-delta",
          id: textId,
          delta: errorText,
        });
        writer.write({ type: "text-end", id: textId });
        writer.write({ type: "finish", finishReason: "stop" });
      }
    },
  });

  return createUIMessageStreamResponse({ stream });
});
