import Foundation
import Testing

@testable import NucleicCore

@Suite("Orchestra orchestration mode")
struct OrchestrationModeTests {
    @Test func detectsOrchestraSentinel() {
        #expect(OrchestrationMode.isOrchestra("orchestra"))
        #expect(OrchestrationMode.isOrchestra("  Orchestra  "))  // trimmed, case-insensitive
        #expect(!OrchestrationMode.isOrchestra("xhigh"))
        #expect(!OrchestrationMode.isOrchestra("high"))
        #expect(!OrchestrationMode.isOrchestra(nil))
    }

    @Test func stillRecognizesLegacyUltracodeSentinel() {
        // Orchestra was renamed from "Ultracode"; a session persisted under the old token must
        // still resolve to the mode, not be sent to a backend verbatim.
        #expect(OrchestrationMode.isOrchestra("ultracode"))
        #expect(OrchestrationMode.isOrchestra("  Ultracode  "))
        #expect(OrchestrationMode.resolvedEffort("ultracode") == "xhigh")
    }

    @Test func resolvesOrchestraToXhigh() {
        // The sentinel never reaches a backend verbatim — it maps to its real effort level.
        #expect(OrchestrationMode.resolvedEffort("orchestra") == "xhigh")
        #expect(OrchestrationMode.resolvedEffort("Orchestra") == "xhigh")
    }

    @Test func passesThroughRealEffortLevels() {
        for level in ["low", "medium", "high", "xhigh", "max"] {
            #expect(OrchestrationMode.resolvedEffort(level) == level)
        }
        #expect(OrchestrationMode.resolvedEffort(nil) == nil)
    }

    @Test func appendsRolePromptOnlyForAnOrchestraRole() {
        // No role: nothing to append when there's no environment guidance either.
        #expect(OrchestrationMode.combinedSystemPrompt(environment: nil, role: nil) == nil)
        // Supervisor → the consent text; worker → the worker briefing.
        #expect(
            OrchestrationMode.combinedSystemPrompt(environment: nil, role: .supervisor)
                == OrchestrationMode.consentPrompt)
        #expect(
            OrchestrationMode.combinedSystemPrompt(environment: nil, role: .worker)
                == OrchestrationMode.workerBriefing)
    }

    @Test func mergesEnvironmentGuidanceWithRolePrompt() {
        let environment = "Build environment: you are running inside a Linux container."
        // No role → only the environment guidance survives.
        #expect(
            OrchestrationMode.combinedSystemPrompt(environment: environment, role: nil) == environment)
        // Supervisor → both, environment first, consent as its own paragraph.
        #expect(
            OrchestrationMode.combinedSystemPrompt(environment: environment, role: .supervisor)
                == environment + "\n\n" + OrchestrationMode.consentPrompt)
        // Worker → environment first, briefing as its own paragraph.
        #expect(
            OrchestrationMode.combinedSystemPrompt(environment: environment, role: .worker)
                == environment + "\n\n" + OrchestrationMode.workerBriefing)
    }

    @Test func consentFramesSupervisorRoleAndDriveLoop() {
        // The contract that makes orchestra work: standing consent to fan out through Nucleic, and
        // the supervisor role framing + drive-loop tools.
        let consent = OrchestrationMode.consentPrompt.lowercased()
        #expect(consent.contains("standing consent"))
        #expect(consent.contains("supervisor"))
        #expect(consent.contains("nucleic_subagent"))
        #expect(consent.contains("nucleic_supervise"))
        #expect(consent.contains("nucleic_reply_to_worker"))
        // The supervisor escalates genuinely user-facing decisions to the human directly.
        #expect(consent.contains("askuserquestion"))
        // Orchestra routes fan-out through Nucleic's managed workers, not the provider's native
        // Task/Agent spawn — the consent must steer the model off those blocked tools.
        #expect(consent.contains("do not use native task/agent"))
    }

    @Test func workerBriefingFramesWorkerRoleAndUpwardChannel() {
        let briefing = OrchestrationMode.workerBriefing.lowercased()
        #expect(briefing.contains("worker"))
        #expect(briefing.contains("supervisor"))
        // Workers reach up via nucleic_ask_supervisor and must NOT try to reach the user directly.
        #expect(briefing.contains("nucleic_ask_supervisor"))
        #expect(briefing.contains("do not use `askuserquestion`"))
    }
}
