import Foundation
import NucleicCore
import Testing

@testable import NucleicApp

@Suite("Transcript render benchmark")
struct TranscriptRenderBenchmarkTests {
    @Test func ordinaryLaunchKeepsProductionRendererWithoutBenchmarkWork() {
        let configuration = TranscriptRenderBenchmarkConfiguration.parse(
            arguments: ["NucleicApp"], environment: [:])

        #expect(configuration.variant == .production)
        #expect(!configuration.isEnabled)
    }

    @Test func launchArgumentSelectsVariantAheadOfEnvironment() {
        let configuration = TranscriptRenderBenchmarkConfiguration.parse(
            arguments: ["NucleicApp", "--transcript-render-variant=generic"],
            environment: [TranscriptRenderBenchmarkConfiguration.environmentKey: "skeletons"])

        #expect(configuration.variant == .genericCards)
        #expect(configuration.isEnabled)
    }

    @Test func splitLaunchArgumentAndEnvironmentFormsAreAccepted() {
        let split = TranscriptRenderBenchmarkConfiguration.parse(
            arguments: ["NucleicApp", "--transcript-render-variant", "text-only"],
            environment: [:])
        let environment = TranscriptRenderBenchmarkConfiguration.parse(
            arguments: ["NucleicApp"],
            environment: [TranscriptRenderBenchmarkConfiguration.environmentKey: "production"])

        #expect(split == .init(variant: .textOnly, isEnabled: true))
        #expect(environment == .init(variant: .production, isEnabled: true))
    }

    @Test func textOnlyVariantKeepsOnlyUserAndAssistantRows() {
        let session = SessionID(rawValue: "benchmark-text")
        let event: (UInt64, AgentEvent.Kind) -> TranscriptItem = { seq, kind in
            .event(AgentEvent(
                sessionID: session, seq: seq, at: .distantPast, backend: .codex,
                nativeType: nil, kind: kind))
        }
        let items: [TranscriptItem] = [
            event(1, .userText(TextChunk(messageID: "u", text: "Question", isPartial: false))),
            .assistant(id: "a", text: "Answer", partial: false),
            .thinking(id: "t", text: "Reasoning", partial: false),
            event(2, .note(NoteEvent(text: "A note"))),
            event(3, .assistantText(TextChunk(
                messageID: "partial", text: "Streaming", isPartial: true))),
        ]

        #expect(items.filter(TranscriptRow.isTextOnlyBenchmarkItem).map(\.id) == [
            "seq-1", "assist-a",
        ])
    }

    @Test func statisticsDescribeNestedAndGroupedCardShapeWithoutCountingHiddenMarkdown() {
        let planText = "# Plan\n\nImplement the benchmark."
        let plan = ToolCall(
            toolCallID: "plan", name: ExitPlanMode.toolName, input: ["plan": .string(planText)])
        let subagent = ToolCall(
            toolCallID: "sub", name: "Task", input: ["prompt": "Inspect rendering"])
        let read = ToolCall(
            toolCallID: "read", name: "Read", input: ["file_path": "Sources/A.swift"])
        let write = ToolCall(
            toolCallID: "write", name: "Write", input: ["file_path": "Sources/B.swift"])
        let nestedTool = ToolCall(
            toolCallID: "nested", name: "Grep", input: ["pattern": "benchmark"])
        let hiddenMarkdown = "This nested prose is collapsed."
        let group: [ToolEntry] = [
            (call: read, result: nil, finished: true, children: []),
            (call: write, result: nil, finished: true, children: [
                .tool(
                    id: "nested", call: nestedTool, result: nil, finished: true,
                    children: [.assistant(
                        id: "hidden", text: hiddenMarkdown, partial: false)])
            ]),
        ]
        let visibleAssistant = "Visible **Markdown**"
        let items: [TranscriptItem] = [
            .assistant(id: "visible", text: visibleAssistant, partial: false),
            .tool(id: "plan", call: plan, result: nil, finished: true, children: []),
            .tool(
                id: "sub", call: subagent, result: nil, finished: true,
                children: [.assistant(id: "sub-answer", text: "Also hidden", partial: false)]),
            .toolGroup(id: "group", signature: 7, calls: group),
        ]

        let statistics = TranscriptRenderBenchmarkStatistics.measure(items)

        #expect(statistics.topLevelRowCount == 4)
        #expect(statistics.nestedChildCount == 3)
        #expect(statistics.maximumNestedDepth == 2)
        #expect(statistics.toolCallCount == 5)
        #expect(statistics.maximumGroupSize == 2)
        #expect(statistics.visibleMarkdownBytes
            == visibleAssistant.utf8.count + planText.utf8.count)
        #expect(statistics.cardKindCounts == [
            "generic": 1,
            "plan": 1,
            "subagent": 1,
            "tool-group": 1,
        ])
        #expect(statistics.cardKindSummary == "generic:1,plan:1,subagent:1,tool-group:1")
    }
}
