import XCTest
@testable import AIFabric

final class SpecializedProviderTests: XCTestCase {

    func testScaffoldUnavailableAndNotImplemented() async throws {
        let p = SpecializedProvider()
        let available = await p.isAvailable
        XCTAssertFalse(available)
        do {
            _ = try await p.complete(AICompletionRequest(task: .vision, prompt: "p"))
            XCTFail("scaffold must throw notImplemented")
        } catch let AIProviderError.notImplemented(id) {
            XCTAssertEqual(id, .specialized)
        }
    }

    /// .vision 체인 [.specialized, .onDevice] — specialized 등록·불가 → onDevice 로 **가시** 폴백(라우터 log).
    /// (onDevice 는 providerUsed=id 를 정직히 반환하는 CountingProvider 사용 — MockAIProvider 는 vision 케이스에서
    ///  providerUsed 를 .specialized 로 하드코딩하므로 부적합.)
    func testVisionFallsBackToOnDeviceVisibly() async throws {
        let sink = LogSink()
        let onDevice = CountingProvider(id: .onDevice, available: true)
        let router = AIRouter(
            providers: [
                .specialized: SpecializedProvider(),
                .onDevice: onDevice,
            ],
            log: { sink.append($0) }
        )
        let resp = try await router.route(AICompletionRequest(task: .vision, prompt: "도면 보기"))
        XCTAssertEqual(resp.providerUsed, .onDevice)
        XCTAssertEqual(resp.routingNote, "fallback from specialized → onDevice")
        let calls = await onDevice.completeCalls
        XCTAssertEqual(calls, 1)
        XCTAssertTrue(sink.lines.contains { $0.contains("specialized") && $0.contains("unavailable") },
                      "specialized 불가가 침묵 아닌 log 로 가시화")
    }
}
