import CodexBarCore
import Commander
import Foundation

extension CodexBarCLI {
    static func runCacheClear(_ values: ParsedValues) {
        let output = CLIOutputPreferences.from(values: values)
        let cookies = values.flags.contains("cookies")
        let cost = values.flags.contains("cost")
        let all = values.flags.contains("all")
        let rawProvider = values.options["provider"]?.last

        let clearCookies = cookies || all
        let clearCost = cost || all

        if !clearCookies, !clearCost {
            Self.exit(
                code: .failure,
                message: "Specify --cookies, --cost, or --all.",
                output: output,
                kind: .args)
        }
        if let error = Self.cacheClearProviderScopeError(rawProvider: rawProvider, clearCost: clearCost) {
            Self.exit(code: .failure, message: error, output: output, kind: .args)
        }

        var results: [CacheClearResult] = []

        if clearCookies {
            if let rawProvider {
                if let provider = ProviderDescriptorRegistry.cliNameMap[rawProvider.lowercased()] {
                    let summary = CookieHeaderCache.clearAllScopesDetailed(provider: provider)
                    results.append(CacheClearResult(
                        cache: "cookies",
                        provider: provider.rawValue,
                        cleared: summary.clearedCount,
                        error: Self.cookieClearError(failedCount: summary.failedCount)))
                } else {
                    Self.exit(
                        code: .failure,
                        message: "Unknown provider: \(rawProvider)",
                        output: output,
                        kind: .args)
                }
            } else {
                let summary = CookieHeaderCache.clearAllDetailed()
                results.append(CacheClearResult(
                    cache: "cookies",
                    provider: nil,
                    cleared: summary.clearedCount,
                    error: Self.cookieClearError(failedCount: summary.failedCount)))
            }
        }

        if clearCost {
            let fm = FileManager.default
            let cacheDir = Self.costUsageCacheDirectory(fileManager: fm)
            var cleared = 0
            var costError: String?
            if fm.fileExists(atPath: cacheDir.path) {
                do {
                    try fm.removeItem(at: cacheDir)
                    cleared = 1
                } catch {
                    costError = error.localizedDescription
                }
            }
            results.append(CacheClearResult(cache: "cost", provider: nil, cleared: cleared, error: costError))
        }

        switch output.format {
        case .text:
            for result in results {
                let scope = result.provider ?? "all providers"
                if let error = result.error {
                    print("\(result.cache): failed to clear (\(scope)) - \(error)")
                } else if result.cleared > 0 {
                    print("\(result.cache): cleared (\(scope))")
                } else {
                    print("\(result.cache): nothing to clear (\(scope))")
                }
            }
        case .json:
            Self.printJSON(results, pretty: output.pretty)
        }

        let hasErrors = results.contains(where: { $0.error != nil })
        Self.exit(code: hasErrors ? .failure : .success, output: output, kind: .runtime)
    }

    static func cacheClearProviderScopeError(rawProvider: String?, clearCost: Bool) -> String? {
        guard rawProvider != nil, clearCost else { return nil }
        return "--provider only scopes cookie caches. Use --cookies --provider <name>, or omit --provider."
    }

    private static func cookieClearError(failedCount: Int) -> String? {
        guard failedCount > 0 else { return nil }
        return "Cookie cache cleanup failed for \(failedCount) operation\(failedCount == 1 ? "" : "s")"
    }
}

struct CacheOptions: CommanderParsable {
    @Flag(names: [.short("v"), .long("verbose")], help: "Enable verbose logging")
    var verbose: Bool = false

    @Flag(name: .long("json-output"), help: "Emit machine-readable logs")
    var jsonOutput: Bool = false

    @Option(name: .long("log-level"), help: "Set log level (trace|verbose|debug|info|warning|error|critical)")
    var logLevel: String?

    @Option(name: .long("format"), help: "Output format: text | json")
    var format: OutputFormat?

    @Flag(name: .long("json"), help: "")
    var jsonShortcut: Bool = false

    @Flag(name: .long("json-only"), help: "Emit JSON only (suppress non-JSON output)")
    var jsonOnly: Bool = false

    @Flag(name: .long("pretty"), help: "Pretty-print JSON output")
    var pretty: Bool = false

    @Flag(name: .long("cookies"), help: "Clear browser cookie caches")
    var cookies: Bool = false

    @Flag(name: .long("cost"), help: "Clear cost usage caches")
    var cost: Bool = false

    @Flag(name: .long("all"), help: "Clear all caches")
    var all: Bool = false

    @Option(name: .long("provider"), help: "Clear cache for a specific provider only")
    var provider: String?
}

private struct CacheClearResult: Encodable {
    let cache: String
    let provider: String?
    let cleared: Int
    var error: String?
}

extension CodexBarCLI {
    /// Mirrors the cost usage cache directory used by the app (UsageStore.costUsageCacheDirectory).
    static func costUsageCacheDirectory(fileManager: FileManager = .default) -> URL {
        let root = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
        return root
            .appendingPathComponent("CodexBar", isDirectory: true)
            .appendingPathComponent("cost-usage", isDirectory: true)
    }
}
