import Foundation
import AIFabric
import DSKit

/// The ONE composition touch-point that names MockAIProvider. When S2 ships real providers,
/// only this file changes (mockProviders -> realProviders) — AIService, views, and intents stay put.
public enum AppAIComposition {
    public static func mockProviders(unavailable: Set<AIProviderID> = []) -> [AIProviderID: any AIProvider] {
        var providers: [AIProviderID: any AIProvider] = [:]
        for id in AIProviderID.allCases {
            providers[id] = MockAIProvider(id: id, available: !unavailable.contains(id))
        }
        return providers
    }

    public static func mockRouter(unavailable: Set<AIProviderID> = []) -> AIRouter {
        AIRouter(
            providers: mockProviders(unavailable: unavailable),
            policy: .default,
            log: { msg in
                #if DEBUG
                print("[route]", msg)
                #endif
            }
        )
    }

    /// FU-B seam: the real S2 fabric (RemoteDS/LocalMLX/OnDevice/Specialized) via `makeDefaultRouter`,
    /// fed S3's concrete `LiveDSAskClient`. The app default stays `mockRouter` (offline scaffold);
    /// switching to live is THIS one call — AIService, views, and intents are unchanged.
    public static func realRouter(
        base: DSBaseURL = .publicTLS,
        token: @escaping @Sendable () async -> String? = { nil }
    ) -> AIRouter {
        makeDefaultRouter(client: LiveDSAskClient(base: base, token: token))
    }
}
