import XCTest
@testable import lichunWebsocket

final class EventV2DecodingTests: XCTestCase {
    var webSocketService: WebSocketService!

    override func setUpWithError() throws {
        try super.setUpWithError()
        continueAfterFailure = false

        let config = URLSessionConfiguration.ephemeral
        config.protocolClasses = [EventV2MockURLProtocol.self]
        let session = URLSession(configuration: config)
        let delegateQueue = OperationQueue()
        webSocketService = WebSocketService(urlSession: session, delegateQueue: delegateQueue)
    }

    override func tearDownWithError() throws {
        webSocketService.disconnect()
        webSocketService = nil
        try super.tearDown()
    }

    func testDecodesEventPromptEnvelope() throws {
        let payload: [String: Any] = [
            "type": "event_prompt",
            "eventId": "event_adult",
            "instanceId": "evt-inst-1",
            "prompt": "Adult prompt",
            "choices": [
                [
                    "choiceId": "help",
                    "text": "Help"
                ]
            ]
        ]

        let envelope = webSocketService.events.decodeEventV2Envelope(from: payload)
        switch envelope {
        case .prompt(let prompt):
            XCTAssertEqual(prompt.eventId, "event_adult")
            XCTAssertEqual(prompt.instanceId, "evt-inst-1")
            XCTAssertEqual(prompt.choices.first?.choiceId, "help")
        default:
            XCTFail("Expected event_prompt envelope")
        }
    }

    func testDecodesEventResolvedEnvelope() throws {
        let payload: [String: Any] = [
            "type": "event_resolved",
            "eventId": "event_adult",
            "instanceId": "evt-inst-1",
            "resolutionText": "You resolved the event."
        ]

        let envelope = webSocketService.events.decodeEventV2Envelope(from: payload)
        switch envelope {
        case .resolved(let resolved):
            XCTAssertEqual(resolved.eventId, "event_adult")
            XCTAssertEqual(resolved.resolutionText, "You resolved the event.")
        default:
            XCTFail("Expected event_resolved envelope")
        }
    }

    func testDecodesEventErrorEnvelope() throws {
        let payload: [String: Any] = [
            "type": "event_error",
            "code": "INVALID_CHOICE",
            "message": "Choice is invalid",
            "eventId": "event_adult",
            "instanceId": "evt-inst-1"
        ]

        let envelope = webSocketService.events.decodeEventV2Envelope(from: payload)
        switch envelope {
        case .error(let eventError):
            XCTAssertEqual(eventError.code, "INVALID_CHOICE")
            XCTAssertEqual(eventError.message, "Choice is invalid")
        default:
            XCTFail("Expected event_error envelope")
        }
    }
}

private final class EventV2MockURLProtocol: URLProtocol {
    override class func canInit(with request: URLRequest) -> Bool {
        true
    }

    override class func canonicalRequest(for request: URLRequest) -> URLRequest {
        request
    }

    override func startLoading() {}
    override func stopLoading() {}
}
