import { renderToStaticMarkup } from "react-dom/server";
import { describe, expect, test } from "vitest";
import {
  AgentConversation,
  AgentMessage,
  AgentPromptInput,
  type AgentChatMessage,
} from "./AgentChat";
import {
  buildSourcesFromToolTrace,
  buildReasoningSteps,
  getToolTraceSummary,
  scrollConversationToBottom,
} from "./agentChatModel";

const assistantMessage: AgentChatMessage = {
  id: "assistant-1",
  role: "assistant",
  content: "Deine groesste Ausgabe war Miete.",
  toolTrace: [
    {
      name: "summarize_transactions",
      inputSummary: "Mai 2026",
      resultSummary: "12 Umsaetze zusammengefasst",
    },
    {
      name: "list_transactions",
      inputSummary: "Miete",
      resultSummary: "1 Treffer",
    },
  ],
};

describe("AgentChat phase 1 components", () => {
  test("scrolls the conversation container directly to the bottom", () => {
    const container = {
      scrollTop: 0,
      scrollHeight: 1200,
    };

    scrollConversationToBottom(container);

    expect(container.scrollTop).toBe(1200);
  });

  test("summarizes tool traces for compact agent transparency", () => {
    expect(getToolTraceSummary(undefined)).toBe("Keine Werkzeuge");
    expect(getToolTraceSummary([])).toBe("Keine Werkzeuge");
    expect(getToolTraceSummary(assistantMessage.toolTrace)).toBe("2 Werkzeuge verwendet");
  });

  test("renders conversation messages with assistant tool trace details", () => {
    const markup = renderToStaticMarkup(
      <AgentConversation
        messages={[
          { id: "user-1", role: "user", content: "Was war teuer?" },
          assistantMessage,
        ]}
      />,
    );

    expect(markup).toContain("Was war teuer?");
    expect(markup).toContain("Deine groesste Ausgabe war Miete.");
    expect(markup).toContain("2 Werkzeuge verwendet");
    expect(markup).toContain("summarize_transactions");
    expect(markup).toContain("12 Umsaetze zusammengefasst");
  });

  test("renders the prompt input with ready and busy states", () => {
    const readyMarkup = renderToStaticMarkup(
      <AgentPromptInput
        value="Bitte analysieren"
        disabled={false}
        isSubmitting={false}
        placeholder="Welche Auswertung soll ich machen?"
        onChange={() => undefined}
        onSubmit={() => undefined}
      />,
    );
    const busyMarkup = renderToStaticMarkup(
      <AgentPromptInput
        value="Bitte analysieren"
        disabled
        isSubmitting
        placeholder="Chat wird vorbereitet..."
        onChange={() => undefined}
        onSubmit={() => undefined}
      />,
    );

    expect(readyMarkup).toContain("Welche Auswertung soll ich machen?");
    expect(readyMarkup).toContain("Senden");
    expect(busyMarkup).toContain("Antwort laeuft");
    expect(busyMarkup).toContain("disabled");
  });

  test("disables prompt submit for whitespace-only input", () => {
    const markup = renderToStaticMarkup(
      <AgentPromptInput
        value="   "
        disabled={false}
        isSubmitting={false}
        placeholder="Welche Auswertung soll ich machen?"
        onChange={() => undefined}
        onSubmit={() => undefined}
      />,
    );

    expect(markup).toContain("disabled");
  });

  test("renders a thinking indicator while the agent is submitting", () => {
    const markup = renderToStaticMarkup(
      <AgentConversation messages={[assistantMessage]} isSubmitting />,
    );

    expect(markup).toContain("Denk mit der KI nach...");
  });

  test("renders a single message without a tool section when no trace exists", () => {
    const markup = renderToStaticMarkup(
      <AgentMessage message={{ id: "assistant-empty", role: "assistant", content: "Hallo" }} />,
    );

    expect(markup).toContain("Assistant");
    expect(markup).toContain("Hallo");
    expect(markup).not.toContain("Werkzeuge verwendet");
  });
});

describe("AgentChat phase 2 reasoning disclosure", () => {
  test("builds safe reasoning steps from tool traces without exposing raw inputs", () => {
    const steps = buildReasoningSteps(assistantMessage.toolTrace);

    expect(steps).toEqual([
      {
        label: "summarize_transactions",
        description: "12 Umsaetze zusammengefasst",
        status: "complete",
      },
      {
        label: "list_transactions",
        description: "1 Treffer",
        status: "complete",
      },
    ]);
    expect(JSON.stringify(steps)).not.toContain("Mai 2026");
  });

  test("renders an assistant work-progress disclosure from tool traces", () => {
    const markup = renderToStaticMarkup(<AgentMessage message={assistantMessage} />);

    expect(markup).toContain("So wurde gearbeitet");
    expect(markup).toContain("summarize_transactions");
    expect(markup).toContain("12 Umsaetze zusammengefasst");
  });

  test("marks the current agent step as active while submitting", () => {
    const markup = renderToStaticMarkup(
      <AgentConversation messages={[assistantMessage]} isSubmitting />,
    );

    expect(markup).toContain("Antwort wird vorbereitet");
    expect(markup).toContain("data-status=\"active\"");
  });
});

describe("AgentChat phase 3 sources and inline citations", () => {
  test("builds private finance sources from tool traces", () => {
    expect(buildSourcesFromToolTrace(assistantMessage.toolTrace)).toEqual([
      {
        id: "tool-1",
        title: "summarize_transactions",
        description: "12 Umsaetze zusammengefasst",
      },
      {
        id: "tool-2",
        title: "list_transactions",
        description: "1 Treffer",
      },
    ]);
  });

  test("renders source list and inline citation markers for assistant messages", () => {
    const markup = renderToStaticMarkup(
      <AgentMessage
        message={{
          id: "assistant-cited",
          role: "assistant",
          content: "Die Miete war der groesste Posten [1].",
          sources: [
            {
              id: "tool-1",
              title: "list_transactions",
              description: "1 Mietumsatz gefunden",
            },
          ],
          citations: [{ marker: "1", sourceId: "tool-1" }],
        }}
      />,
    );

    expect(markup).toContain("Quellen");
    expect(markup).toContain("list_transactions");
    expect(markup).toContain("1 Mietumsatz gefunden");
    expect(markup).toContain("[1]");
    expect(markup).toContain("data-source-id=\"tool-1\"");
  });
});
