import { describe, expect, it } from "vitest";

import {
  buildLatestUpdatePatch,
  resolveLatestUpdateIntent,
} from "@/features/agents/operations/latestUpdateWorkflow";
import {
  buildReconcileTerminalPatch,
  resolveReconcileEligibility,
  resolveReconcileWaitOutcome,
  resolveSummarySnapshotIntent,
} from "@/features/agents/operations/fleetLifecycleWorkflow";
import { buildSummarySnapshotPatches } from "@/features/agents/state/runtimeEventBridge";
import type { AgentState } from "@/features/agents/state/store";

const createAgent = (agentId: string, sessionKey: string, status: AgentState["status"]): AgentState => ({
  agentId,
  name: agentId,
  sessionKey,
  status,
  sessionCreated: true,
  awaitingUserInput: false,
  hasUnseenActivity: false,
  outputLines: [],
  lastResult: null,
  lastDiff: null,
  runId: status === "running" ? "run-1" : null,
  runStartedAt: status === "running" ? 1 : null,
  streamText: null,
  thinkingTrace: null,
  latestOverride: null,
  latestOverrideKind: null,
  lastAssistantMessageAt: null,
  lastActivityAt: null,
  latestPreview: null,
  lastUserMessage: null,
  draft: "",
  sessionSettingsSynced: true,
  historyLoadedAt: null,
  historyFetchLimit: null,
  historyFetchedCount: null,
  historyMaybeTruncated: false,
  toolCallingEnabled: true,
  showThinkingTraces: true,
  model: "openai/gpt-5",
  thinkingLevel: "medium",
  avatarSeed: agentId,
  avatarUrl: null,
});

describe("fleetLifecycleWorkflow integration", () => {
  it("page adapter applies latest-update reset/update intents without behavior drift", () => {
    const resetIntent = resolveLatestUpdateIntent({
      message: "regular prompt",
      agentId: "agent-1",
      sessionKey: "agent:agent-1:main",
      hasExistingOverride: true,
    });
    expect(resetIntent).toEqual({ kind: "reset" });
    expect(buildLatestUpdatePatch("")).toEqual({
      latestOverride: null,
      latestOverrideKind: null,
    });

    const heartbeatIntent = resolveLatestUpdateIntent({
      message: "heartbeat status please",
      agentId: "",
      sessionKey: "agent:agent-1:main",
      hasExistingOverride: false,
    });
    expect(heartbeatIntent).toEqual({
      kind: "fetch-heartbeat",
      agentId: "agent-1",
      sessionLimit: 48,
      historyLimit: 200,
    });
    expect(buildLatestUpdatePatch("Heartbeat is healthy.", "heartbeat")).toEqual({
      latestOverride: "Heartbeat is healthy.",
      latestOverrideKind: "heartbeat",
    });
  });

  it("summary snapshot flow preserves status + preview patch application semantics", () => {
    const agents = [
      createAgent("agent-1", "agent:agent-1:main", "idle"),
      createAgent("agent-2", "agent:agent-2:main", "running"),
    ];
    const summaryIntent = resolveSummarySnapshotIntent({
      agents,
      maxKeys: 64,
    });
    expect(summaryIntent).toEqual({
      kind: "fetch",
      keys: ["agent:agent-1:main", "agent:agent-2:main"],
      limit: 8,
      maxChars: 240,
    });

    const patches = buildSummarySnapshotPatches({
      agents,
      statusSummary: {
        sessions: {
          recent: [{ key: "agent:agent-1:main", updatedAt: 1234 }],
          byAgent: [],
        },
      },
      previewResult: {
        ts: 1234,
        previews: [
          {
            key: "agent:agent-1:main",
            status: "ok",
            items: [
              { role: "user", text: "ping", timestamp: 1000 },
              { role: "assistant", text: "pong", timestamp: 1200 },
            ],
          },
        ],
      },
    });

    expect(patches).toEqual([
      {
        agentId: "agent-1",
        patch: {
          lastActivityAt: 1234,
          lastAssistantMessageAt: 1200,
          latestPreview: "pong",
          lastUserMessage: "ping",
        },
      },
    ]);
  });

  it("run reconciliation preserves terminal transition semantics and history reload trigger", () => {
    const runReconcileAdapter = (params: {
      status: AgentState["status"];
      sessionCreated: boolean;
      runId: string | null;
      waitStatus: unknown;
    }) => {
      const eligibility = resolveReconcileEligibility({
        status: params.status,
        sessionCreated: params.sessionCreated,
        runId: params.runId,
      });
      if (!eligibility.shouldCheck) {
        return { patch: null, shouldReloadHistory: false };
      }
      const outcome = resolveReconcileWaitOutcome(params.waitStatus);
      if (!outcome) {
        return { patch: null, shouldReloadHistory: false };
      }
      return {
        patch: buildReconcileTerminalPatch({ outcome }),
        shouldReloadHistory: true,
      };
    };

    expect(
      runReconcileAdapter({
        status: "running",
        sessionCreated: true,
        runId: "run-1",
        waitStatus: "ok",
      })
    ).toEqual({
      patch: {
        status: "idle",
        runId: null,
        runStartedAt: null,
        streamText: null,
        thinkingTrace: null,
      },
      shouldReloadHistory: true,
    });
    expect(
      runReconcileAdapter({
        status: "running",
        sessionCreated: true,
        runId: "run-1",
        waitStatus: "error",
      })
    ).toEqual({
      patch: {
        status: "error",
        runId: null,
        runStartedAt: null,
        streamText: null,
        thinkingTrace: null,
      },
      shouldReloadHistory: true,
    });
  });
});
