import Foundation
import AIFabric

/// Renderable failure (the UI never sees a raw AIRoutingError — that would break the
/// "visible error, not silent fallback" contract).
public enum AIServiceError: Error, Sendable {
    case explicitUnavailable(AIProviderID)
    case notConfigured(AIProviderID)
    case noneAvailable(AITask)
    case providerFailed(String)
    case unknown(String)
}

public enum AIResult: Sendable {
    case success(AICompletionResponse)
    case failure(AIServiceError)
}

/// The single app-facing facade over the S2 fabric. Views call intent methods; AIService is the ONLY
/// place AICompletionRequest is built. An actor (not @Observable): routing is async work that should
/// serialize and not hop to MainActor.
public actor AIService {
    private let router: AIRouter

    public init(router: AIRouter) { self.router = router }

    private func run(_ request: AICompletionRequest) async -> AIResult {
        do {
            return .success(try await router.route(request))
        } catch let e as AIRoutingError {
            switch e {
            case .explicitProviderUnavailable(let id): return .failure(.explicitUnavailable(id))
            case .providerNotConfigured(let id): return .failure(.notConfigured(id))
            case .noProviderAvailable(let t): return .failure(.noneAvailable(t))
            }
        } catch let e as AIProviderError {
            return .failure(.providerFailed("\(e)"))
        } catch {
            return .failure(.unknown("\(error)"))
        }
    }

    // Intent methods — UI gesture -> AITask. (vision is deferred: the frozen request is text-only.)
    public func summarize(text: String) async -> AIResult {
        await run(AICompletionRequest(task: .quickSummarize, prompt: "다음 문서를 요약", context: text))
    }
    public func memoAssist(content: String) async -> AIResult {
        await run(AICompletionRequest(task: .memoAssist, prompt: "제목과 태그 제안", context: content))
    }
    public func askSelection(selection: String, question: String) async -> AIResult {
        await run(AICompletionRequest(task: .askSelection, prompt: question, context: selection))
    }
    public func corpusAsk(question: String, explicit: AIProviderID? = nil) async -> AIResult {
        await run(AICompletionRequest(task: .corpusAsk, prompt: question, context: nil, explicitProvider: explicit))
    }
    public func classify(documentText: String) async -> AIResult {
        await run(AICompletionRequest(task: .classify, prompt: "도메인/카테고리 분류 제안", context: documentText))
    }
}
