import Foundation
#if canImport(FoundationNetworking)
import FoundationNetworking
#endif

// swiftlint:disable type_body_length
public struct AlibabaCodingPlanUsageFetcher: Sendable {
    private static let log = CodexBarLog.logger("alibaba-coding-plan")
    private static let browserLikeUserAgent =
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " +
        "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/143.0.0.0 Safari/537.36"
    private static let safariLikeUserAgent =
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) " +
        "AppleWebKit/605.1.15 (KHTML, like Gecko) Version/26.3 Safari/605.1.15"

    enum AuthMode {
        case apiKey
        case webSession
    }

    public static func fetchUsage(
        apiKey: String,
        region: AlibabaCodingPlanAPIRegion = .international,
        environment: [String: String] = ProcessInfo.processInfo.environment,
        now: Date = Date(),
        transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> AlibabaCodingPlanUsageSnapshot
    {
        let cleanedKey = apiKey.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !cleanedKey.isEmpty else {
            throw AlibabaCodingPlanUsageError.invalidCredentials
        }
        if let rejectedKey = AlibabaCodingPlanSettingsReader.rejectedEndpointOverrideKey(environment: environment) {
            throw ProviderEndpointOverrideError.alibabaCodingPlan(rejectedKey)
        }

        if region != .international {
            return try await self.fetchUsageOnce(
                apiKey: cleanedKey,
                region: region,
                environment: environment,
                now: now,
                transport: transport)
        }

        do {
            return try await self.fetchUsageOnce(
                apiKey: cleanedKey,
                region: .international,
                environment: environment,
                now: now,
                transport: transport)
        } catch let error as AlibabaCodingPlanUsageError {
            guard error.shouldRetryOnAlternateRegion else { throw error }
            Self.log.debug("Alibaba Coding Plan request failed on intl host; retrying cn host")
            return try await self.fetchUsageOnce(
                apiKey: cleanedKey,
                region: .chinaMainland,
                environment: environment,
                now: now,
                transport: transport)
        }
    }

    public static func fetchUsage(
        cookieHeader: String,
        region: AlibabaCodingPlanAPIRegion = .international,
        environment: [String: String] = ProcessInfo.processInfo.environment,
        now: Date = Date(),
        transport: any ProviderHTTPTransport = ProviderHTTPClient.shared) async throws -> AlibabaCodingPlanUsageSnapshot
    {
        guard let normalizedCookie = CookieHeaderNormalizer.normalize(cookieHeader) else {
            throw AlibabaCodingPlanSettingsError.invalidCookie
        }
        if let rejectedKey = AlibabaCodingPlanSettingsReader.rejectedEndpointOverrideKey(environment: environment) {
            throw ProviderEndpointOverrideError.alibabaCodingPlan(rejectedKey)
        }

        if region != .international {
            return try await self.fetchUsageOnce(
                cookieHeader: normalizedCookie,
                region: region,
                environment: environment,
                now: now,
                transport: transport)
        }

        do {
            return try await self.fetchUsageOnce(
                cookieHeader: normalizedCookie,
                region: .international,
                environment: environment,
                now: now,
                transport: transport)
        } catch let error as AlibabaCodingPlanUsageError {
            guard error.shouldRetryOnAlternateRegion else { throw error }
            Self.log.debug("Alibaba Coding Plan cookie request failed on intl host; retrying cn host")
            return try await self.fetchUsageOnce(
                cookieHeader: normalizedCookie,
                region: .chinaMainland,
                environment: environment,
                now: now,
                transport: transport)
        }
    }

    private static func fetchUsageOnce(
        apiKey: String,
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String],
        now: Date,
        transport: any ProviderHTTPTransport) async throws -> AlibabaCodingPlanUsageSnapshot
    {
        let url = self.resolveQuotaURL(region: region, environment: environment)
        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = self.queryCodingPlanAPIRequestBody(region: region)
        request.setValue("application/json", forHTTPHeaderField: "Content-Type")
        request.setValue("application/json", forHTTPHeaderField: "Accept")
        request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
        request.setValue(apiKey, forHTTPHeaderField: "x-api-key")
        request.setValue(apiKey, forHTTPHeaderField: "X-DashScope-API-Key")
        request.setValue(Self.browserLikeUserAgent, forHTTPHeaderField: "User-Agent")
        request.setValue(region.gatewayBaseURLString, forHTTPHeaderField: "Origin")
        request.setValue(region.dashboardURL.absoluteString, forHTTPHeaderField: "Referer")

        let response = try await transport.response(for: request)
        let data = response.data
        guard response.statusCode == 200 else {
            if response.statusCode == 401 || response.statusCode == 403 {
                throw AlibabaCodingPlanUsageError.invalidCredentials
            }
            let body = String(data: data, encoding: .utf8) ?? ""
            Self.log.error("Alibaba Coding Plan returned \(response.statusCode): \(body)")
            throw AlibabaCodingPlanUsageError.apiError("HTTP \(response.statusCode)")
        }

        return try self.parseUsageSnapshot(from: data, now: now, authMode: .apiKey)
    }

    private static func fetchUsageOnce(
        cookieHeader: String,
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String],
        now: Date,
        transport: any ProviderHTTPTransport) async throws -> AlibabaCodingPlanUsageSnapshot
    {
        let url = self.resolveConsoleQuotaURL(region: region, environment: environment)
        let secToken = try await self.resolveConsoleSECToken(
            cookieHeader: cookieHeader,
            region: region,
            environment: environment,
            transport: transport)
        let anonymousID = self.extractCookieValue(name: "cna", from: cookieHeader)

        var request = URLRequest(url: url)
        request.httpMethod = "POST"
        request.httpBody = self.queryCodingPlanConsoleRequestBody(
            region: region,
            secToken: secToken,
            anonymousID: anonymousID)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.setValue("*/*", forHTTPHeaderField: "Accept")
        request.setValue(cookieHeader, forHTTPHeaderField: "Cookie")
        if let csrf = self.extractCookieValue(name: "login_aliyunid_csrf", from: cookieHeader) ??
            self.extractCookieValue(name: "csrf", from: cookieHeader)
        {
            request.setValue(csrf, forHTTPHeaderField: "x-xsrf-token")
            request.setValue(csrf, forHTTPHeaderField: "x-csrf-token")
        }
        request.setValue("XMLHttpRequest", forHTTPHeaderField: "X-Requested-With")
        request.setValue(Self.browserLikeUserAgent, forHTTPHeaderField: "User-Agent")
        request.setValue(region.gatewayBaseURLString, forHTTPHeaderField: "Origin")
        request.setValue(region.consoleRefererURL.absoluteString, forHTTPHeaderField: "Referer")

        let response = try await transport.response(for: request)
        let data = response.data
        guard response.statusCode == 200 else {
            if response.statusCode == 401 || response.statusCode == 403 {
                throw AlibabaCodingPlanUsageError.loginRequired
            }
            let body = String(data: data, encoding: .utf8) ?? ""
            Self.log.error("Alibaba Coding Plan returned \(response.statusCode): \(body)")
            throw AlibabaCodingPlanUsageError.apiError("HTTP \(response.statusCode)")
        }

        return try self.parseUsageSnapshot(from: data, now: now, authMode: .webSession)
    }

    private static func queryCodingPlanAPIRequestBody(region: AlibabaCodingPlanAPIRegion) -> Data {
        let payload: [String: Any] = [
            "queryCodingPlanInstanceInfoRequest": [
                "commodityCode": region.commodityCode,
            ],
        ]
        return (try? JSONSerialization.data(withJSONObject: payload, options: [])) ?? Data("{}".utf8)
    }

    private static func queryCodingPlanConsoleRequestBody(
        region: AlibabaCodingPlanAPIRegion,
        secToken: String,
        anonymousID: String?) -> Data
    {
        let traceID = UUID().uuidString.lowercased()
        var cornerstoneParam: [String: Any] = [
            "feTraceId": traceID,
            "feURL": region.dashboardURL.absoluteString,
            "protocol": "V2",
            "console": "ONE_CONSOLE",
            "productCode": "p_efm",
            "domain": region.consoleDomain,
            "consoleSite": region.consoleSite,
            "userNickName": "",
            "userPrincipalName": "",
            "xsp_lang": "en-US",
        ]
        if let anonymousID, !anonymousID.isEmpty {
            cornerstoneParam["X-Anonymous-Id"] = anonymousID
        }

        let paramsObject: [String: Any] = [
            "Api": region.consoleQuotaAPIName,
            "V": "1.0",
            "Data": [
                "queryCodingPlanInstanceInfoRequest": [
                    "commodityCode": region.commodityCode,
                    "onlyLatestOne": true,
                ],
                "cornerstoneParam": cornerstoneParam,
            ],
        ]

        guard let paramsData = try? JSONSerialization.data(withJSONObject: paramsObject, options: []),
              let paramsString = String(data: paramsData, encoding: .utf8)
        else {
            return Data()
        }

        var components = URLComponents()
        components.queryItems = [
            URLQueryItem(name: "params", value: paramsString),
            URLQueryItem(name: "region", value: region.currentRegionID),
            URLQueryItem(name: "sec_token", value: secToken),
        ]
        return Data((components.percentEncodedQuery ?? "").utf8)
    }

    static func resolveConsoleQuotaURL(
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String]) -> URL
    {
        if let override = AlibabaCodingPlanSettingsReader.quotaURL(environment: environment) {
            return override
        }
        if let host = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment),
           let hostURL = self.consoleURL(from: host, region: region)
        {
            return hostURL
        }
        return region.consoleRPCURL
    }

    static func resolveQuotaURL(
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String]) -> URL
    {
        if let override = AlibabaCodingPlanSettingsReader.quotaURL(environment: environment) {
            return override
        }
        if let host = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment),
           let hostURL = self.url(from: host, region: region)
        {
            return hostURL
        }
        return region.quotaURL
    }

    static func resolveConsoleDashboardURL(
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String]) -> URL
    {
        if let override = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment),
           let hostURL = self.dashboardURL(from: override, region: region)
        {
            return hostURL
        }
        return region.dashboardURL
    }

    static func url(from rawHost: String, region: AlibabaCodingPlanAPIRegion) -> URL? {
        let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost)
        guard let cleaned else { return nil }

        let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned)
        guard let base else { return nil }

        var components = URLComponents(url: base, resolvingAgainstBaseURL: false)
        components?.path = "/data/api.json"
        components?.queryItems = [
            URLQueryItem(
                name: "action",
                value: "zeldaEasy.broadscope-bailian.codingPlan.queryCodingPlanInstanceInfoV2"),
            URLQueryItem(name: "product", value: "broadscope-bailian"),
            URLQueryItem(name: "api", value: "queryCodingPlanInstanceInfoV2"),
            URLQueryItem(name: "currentRegionId", value: region.currentRegionID),
        ]
        return components?.url
    }

    static func consoleURL(from rawHost: String, region: AlibabaCodingPlanAPIRegion) -> URL? {
        let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost)
        guard let cleaned else { return nil }

        let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned)
        guard let base else { return nil }

        var components = URLComponents(url: base, resolvingAgainstBaseURL: false)
        components?.path = "/data/api.json"
        components?.queryItems = [
            URLQueryItem(name: "action", value: region.consoleRPCAction),
            URLQueryItem(name: "product", value: region.consoleRPCProduct),
            URLQueryItem(name: "api", value: region.consoleQuotaAPIName),
            URLQueryItem(name: "_v", value: "undefined"),
        ]
        return components?.url
    }

    private static func resolveConsoleSECToken(
        cookieHeader: String,
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String],
        transport: any ProviderHTTPTransport) async throws -> String
    {
        let cookieSECToken = self.extractCookieValue(name: "sec_token", from: cookieHeader)

        let dashboardURL = self.resolveConsoleDashboardURL(region: region, environment: environment)

        var request = URLRequest(url: dashboardURL)
        request.httpMethod = "GET"
        request.setValue(cookieHeader, forHTTPHeaderField: "Cookie")
        request.setValue(Self.safariLikeUserAgent, forHTTPHeaderField: "User-Agent")
        request.setValue(
            "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
            forHTTPHeaderField: "Accept")

        if let response = try? await transport.response(for: request),
           response.statusCode == 200,
           let html = String(data: response.data, encoding: .utf8),
           let token = self.extractConsoleSECToken(from: html),
           !token.isEmpty
        {
            return token
        }

        if let token = try? await self.fetchSECTokenFromUserInfo(
            cookieHeader: cookieHeader,
            region: region,
            environment: environment,
            transport: transport)
        {
            return token
        }

        if let cookieSECToken, !cookieSECToken.isEmpty {
            return cookieSECToken
        }

        throw AlibabaCodingPlanUsageError.loginRequired
    }

    static func dashboardURL(from rawHost: String, region: AlibabaCodingPlanAPIRegion) -> URL? {
        let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost)
        guard let cleaned else { return nil }

        let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned)
        guard let base else { return nil }

        guard var components = URLComponents(url: base, resolvingAgainstBaseURL: false),
              let dashboardComponents = URLComponents(
                  url: region.dashboardURL,
                  resolvingAgainstBaseURL: false)
        else {
            return nil
        }

        components.path = dashboardComponents.path
        components.percentEncodedQuery = dashboardComponents.percentEncodedQuery
        components.fragment = dashboardComponents.fragment
        return components.url
    }

    private static func fetchSECTokenFromUserInfo(
        cookieHeader: String,
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String],
        transport: any ProviderHTTPTransport) async throws -> String?
    {
        let gatewayBaseURL = self.resolveConsoleGatewayBaseURL(region: region, environment: environment)
        let userInfoURL = gatewayBaseURL.appendingPathComponent("tool/user/info.json")
        var request = URLRequest(url: userInfoURL)
        request.httpMethod = "GET"
        request.setValue(cookieHeader, forHTTPHeaderField: "Cookie")
        request.setValue(Self.safariLikeUserAgent, forHTTPHeaderField: "User-Agent")
        request.setValue("application/json, text/plain, */*", forHTTPHeaderField: "Accept")
        let referer = gatewayBaseURL.absoluteString.hasSuffix("/") ? gatewayBaseURL.absoluteString : gatewayBaseURL
            .absoluteString + "/"
        request.setValue(referer, forHTTPHeaderField: "Referer")

        let response = try await transport.response(for: request)
        guard response.statusCode == 200 else {
            return nil
        }

        let object = try JSONSerialization.jsonObject(with: response.data, options: [])
        let expanded = self.expandedJSON(object)
        return self.findFirstString(forKeys: ["secToken", "sec_token"], in: expanded)
    }

    private static func resolveConsoleGatewayBaseURL(
        region: AlibabaCodingPlanAPIRegion,
        environment: [String: String]) -> URL
    {
        if let host = AlibabaCodingPlanSettingsReader.hostOverride(environment: environment),
           let hostURL = self.baseURL(from: host)
        {
            return hostURL
        }
        return URL(string: region.gatewayBaseURLString)!
    }

    private static func baseURL(from rawHost: String) -> URL? {
        let cleaned = AlibabaCodingPlanSettingsReader.cleaned(rawHost)
        guard let cleaned else { return nil }

        let base = ProviderEndpointOverrideValidator.normalizedHTTPSURL(from: cleaned)
        guard let base else { return nil }

        guard var components = URLComponents(url: base, resolvingAgainstBaseURL: false) else {
            return nil
        }
        components.path = ""
        components.query = nil
        components.fragment = nil
        return components.url
    }

    static func parseUsageSnapshot(
        from data: Data,
        now: Date = Date(),
        authMode: AuthMode = .webSession) throws -> AlibabaCodingPlanUsageSnapshot
    {
        guard !data.isEmpty else {
            throw AlibabaCodingPlanUsageError.parseFailed("Empty response body")
        }

        let object = try JSONSerialization.jsonObject(with: data, options: [])
        let expanded = self.expandedJSON(object)
        guard let dictionary = expanded as? [String: Any] else {
            throw AlibabaCodingPlanUsageError.parseFailed("Unexpected payload")
        }

        if let statusCode = self.findFirstInt(forKeys: ["statusCode", "status_code", "code"], in: dictionary),
           statusCode != 0,
           statusCode != 200
        {
            let message = self.findFirstString(
                forKeys: ["statusMessage", "status_msg", "message", "msg"],
                in: dictionary)
                ?? "status code \(statusCode)"
            let lower = message.lowercased()
            if statusCode == 401 || statusCode == 403 || lower.contains("api key") || lower.contains("unauthorized") {
                throw AlibabaCodingPlanUsageError.invalidCredentials
            }
            throw AlibabaCodingPlanUsageError.apiError(message)
        }

        if let codeText = self.findFirstString(forKeys: ["code", "status", "statusCode"], in: dictionary) {
            let normalizedCode = codeText.lowercased()
            if normalizedCode.contains("needlogin") || normalizedCode.contains("login") {
                if authMode == .apiKey {
                    throw AlibabaCodingPlanUsageError.apiKeyUnavailableInRegion
                }
                throw AlibabaCodingPlanUsageError.loginRequired
            }
        }
        if let messageText = self.findFirstString(forKeys: ["message", "msg", "statusMessage"], in: dictionary) {
            let normalizedMessage = messageText.lowercased()
            if normalizedMessage.contains("log in") || normalizedMessage.contains("login") {
                if authMode == .apiKey {
                    throw AlibabaCodingPlanUsageError.apiKeyUnavailableInRegion
                }
                throw AlibabaCodingPlanUsageError.loginRequired
            }
            if authMode == .apiKey,
               normalizedMessage.contains("console session") ||
               normalizedMessage.contains("api key mode may be unavailable")
            {
                throw AlibabaCodingPlanUsageError.apiKeyUnavailableInRegion
            }
        }

        let instanceInfo = self.findActiveInstanceInfo(in: dictionary, now: now)
        let instanceCount = self.findFirstArray(
            forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"],
            in: dictionary)?
            .compactMap { $0 as? [String: Any] }
            .count ?? 0
        let shouldScopeQuotaToSelectedInstance =
            instanceCount > 1 &&
            (instanceInfo.map { self.activeSignalScore(in: $0, now: now) > 0 } ?? false)
        let quota = if shouldScopeQuotaToSelectedInstance, let instanceInfo {
            self.findQuotaInfo(in: instanceInfo)
        } else {
            self.findQuotaInfo(in: instanceInfo ?? [:]) ?? self.findQuotaInfo(in: dictionary)
        }
        guard let quota else {
            if let fallback = self.parsePlanVisibleActiveFallback(
                payload: dictionary,
                instanceInfo: instanceInfo,
                now: now)
            {
                return fallback
            }
            let diagnostics = self.payloadDiagnostics(payload: dictionary)
            Self.log.error("Alibaba coding plan quota payload missing expected fields: \(diagnostics)")
            throw AlibabaCodingPlanUsageError.parseFailed("Missing coding plan quota data (\(diagnostics))")
        }

        let planName = self.findPlanName(in: instanceInfo ?? [:]) ?? self.findPlanName(in: dictionary)

        let snapshot = AlibabaCodingPlanUsageSnapshot(
            planName: planName,
            fiveHourUsedQuota: self.anyInt(for: ["per5HourUsedQuota", "perFiveHourUsedQuota"], in: quota),
            fiveHourTotalQuota: self.anyInt(for: ["per5HourTotalQuota", "perFiveHourTotalQuota"], in: quota),
            fiveHourNextRefreshTime: self.anyDate(
                for: ["per5HourQuotaNextRefreshTime", "perFiveHourQuotaNextRefreshTime"],
                in: quota),
            weeklyUsedQuota: self.anyInt(for: ["perWeekUsedQuota"], in: quota),
            weeklyTotalQuota: self.anyInt(for: ["perWeekTotalQuota"], in: quota),
            weeklyNextRefreshTime: self.anyDate(for: ["perWeekQuotaNextRefreshTime"], in: quota),
            monthlyUsedQuota: self.anyInt(for: ["perBillMonthUsedQuota", "perMonthUsedQuota"], in: quota),
            monthlyTotalQuota: self.anyInt(for: ["perBillMonthTotalQuota", "perMonthTotalQuota"], in: quota),
            monthlyNextRefreshTime: self.anyDate(
                for: ["perBillMonthQuotaNextRefreshTime", "perMonthQuotaNextRefreshTime"],
                in: quota),
            updatedAt: now)

        if snapshot.fiveHourTotalQuota == nil,
           snapshot.weeklyTotalQuota == nil,
           snapshot.monthlyTotalQuota == nil
        {
            if let fallback = self.parsePlanVisibleActiveFallback(
                payload: dictionary,
                instanceInfo: instanceInfo,
                now: now)
            {
                return fallback
            }
            let diagnostics = self.payloadDiagnostics(payload: dictionary)
            Self.log.error("Alibaba coding plan payload had no usable windows: \(diagnostics)")
            throw AlibabaCodingPlanUsageError.parseFailed("No quota windows found in payload (\(diagnostics))")
        }

        return snapshot
    }

    private static func findPlanName(in payload: [String: Any]) -> String? {
        if let infos = self.findFirstArray(
            forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"],
            in: payload)
        {
            for item in infos {
                guard let info = item as? [String: Any] else { continue }
                let candidates = [
                    self.anyString(for: ["planName", "plan_name"], in: info),
                    self.anyString(for: ["instanceName", "instance_name"], in: info),
                    self.anyString(for: ["packageName", "package_name"], in: info),
                ]
                for candidate in candidates {
                    if let candidate, !candidate.isEmpty {
                        return candidate
                    }
                }
            }
        }
        return self.findFirstString(forKeys: ["planName", "plan_name", "packageName", "package_name"], in: payload)
    }

    private static func findActiveInstanceInfo(in payload: [String: Any], now: Date = Date()) -> [String: Any]? {
        guard let infos = self.findFirstArray(
            forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"],
            in: payload)
        else {
            return nil
        }

        var first: [String: Any]?
        var best: [String: Any]?
        var bestScore = Int.min
        for item in infos {
            guard let info = item as? [String: Any] else { continue }
            first = first ?? info
            let score = self.activeSignalScore(in: info, now: now)
            if score > bestScore {
                best = info
                bestScore = score
            }
        }
        if bestScore > 0 {
            return best
        }
        return first
    }

    private static func parsePlanVisibleActiveFallback(
        payload: [String: Any],
        instanceInfo: [String: Any]?,
        now: Date) -> AlibabaCodingPlanUsageSnapshot?
    {
        let source = instanceInfo ?? payload
        guard self.hasPositiveActivePlanSignal(in: source, payload: payload, now: now),
              let planName = self.findPlanName(in: source) ?? self.findPlanName(in: payload)
        else {
            return nil
        }

        return AlibabaCodingPlanUsageSnapshot(
            planName: planName,
            fiveHourUsedQuota: nil,
            fiveHourTotalQuota: nil,
            fiveHourNextRefreshTime: nil,
            weeklyUsedQuota: nil,
            weeklyTotalQuota: nil,
            weeklyNextRefreshTime: nil,
            monthlyUsedQuota: nil,
            monthlyTotalQuota: nil,
            monthlyNextRefreshTime: nil,
            updatedAt: now)
    }

    private static func hasPositiveActivePlanSignal(
        in source: [String: Any],
        payload: [String: Any],
        now: Date) -> Bool
    {
        if self.containsPlanInstances(in: payload) {
            return self.activeSignalScore(in: source, now: now) > 0
        }
        return self.activeSignalScore(in: source, now: now) > 0 || self.activeSignalScore(in: payload, now: now) > 0
    }

    private static func containsPlanInstances(in payload: [String: Any]) -> Bool {
        guard let infos = self.findFirstArray(
            forKeys: ["codingPlanInstanceInfos", "coding_plan_instance_infos"],
            in: payload)
        else {
            return false
        }
        return infos.contains { $0 is [String: Any] }
    }

    private static func activeSignalScore(in source: [String: Any], now: Date) -> Int {
        if let status = self.anyString(for: ["status", "instanceStatus"], in: source)?.uppercased() {
            if ["VALID", "ACTIVE"].contains(status) {
                return 3
            }
            if ["EXPIRED", "INVALID", "INACTIVE", "DISABLED", "TERMINATED", "STOPPED"].contains(status) {
                return -1
            }
        }

        if let isActive = self.anyBool(for: ["isActive", "active"], in: source) {
            return isActive ? 3 : -1
        }

        if let expiry = self.anyDate(for: ["endTime", "periodEndTime", "expireTime", "expirationTime"], in: source),
           expiry.timeIntervalSince(now) > 0
        {
            return 1
        }

        return 0
    }

    private static func payloadDiagnostics(payload: [String: Any]) -> String {
        let topKeys = payload.keys.sorted()
        let dataDict = self.findFirstDictionary(forKeys: ["data", "successResponse", "success_response"], in: payload)
        let dataKeys = dataDict?.keys.sorted() ?? []
        let instanceInfo = self.findActiveInstanceInfo(in: payload)
        let instanceKeys = instanceInfo?.keys.sorted() ?? []
        let hasQuota = self.findQuotaInfo(in: payload) != nil
        let planUsage =
            self.anyString(for: ["planUsage", "usageRate", "usage", "usageValue"], in: instanceInfo ?? [:]) ??
            self.findFirstString(forKeys: ["planUsage", "usageRate", "usage", "usageValue"], in: payload)
        let compactPlanUsage = planUsage?.replacingOccurrences(of: "\n", with: " ") ?? "none"
        let status = self.anyString(for: ["status", "instanceStatus"], in: instanceInfo ?? [:]) ?? "none"

        return "topKeys=\(topKeys.joined(separator: ",")) dataKeys=\(dataKeys.joined(separator: ",")) " +
            "instanceKeys=\(instanceKeys.joined(separator: ",")) hasQuota=\(hasQuota ? "1" : "0") " +
            "status=\(status) planUsage=\(compactPlanUsage)"
    }

    private static func findQuotaInfo(in payload: [String: Any]) -> [String: Any]? {
        if let direct = self.findFirstDictionary(
            forKeys: ["codingPlanQuotaInfo", "coding_plan_quota_info"],
            in: payload)
        {
            return direct
        }
        return self.findFirstDictionary(
            matchingAnyKey: [
                "per5HourUsedQuota",
                "per5HourTotalQuota",
                "perWeekUsedQuota",
                "perWeekTotalQuota",
                "perBillMonthUsedQuota",
                "perBillMonthTotalQuota",
            ],
            in: payload)
    }

    private static func findFirstDictionary(forKeys keys: [String], in value: Any) -> [String: Any]? {
        guard let dict = value as? [String: Any] else { return nil }
        for key in keys {
            if let nested = dict[key] as? [String: Any] {
                return nested
            }
        }
        for nestedValue in dict.values {
            if let nested = self.findFirstDictionary(forKeys: keys, in: nestedValue) {
                return nested
            }
        }
        if let array = value as? [Any] {
            for item in array {
                if let nested = self.findFirstDictionary(forKeys: keys, in: item) {
                    return nested
                }
            }
        }
        return nil
    }

    private static func findFirstDictionary(matchingAnyKey keys: [String], in value: Any) -> [String: Any]? {
        if let dict = value as? [String: Any] {
            if keys.contains(where: { dict[$0] != nil }) {
                return dict
            }
            for nestedValue in dict.values {
                if let nested = self.findFirstDictionary(matchingAnyKey: keys, in: nestedValue) {
                    return nested
                }
            }
            return nil
        }
        if let array = value as? [Any] {
            for item in array {
                if let nested = self.findFirstDictionary(matchingAnyKey: keys, in: item) {
                    return nested
                }
            }
        }
        return nil
    }

    private static func findFirstArray(forKeys keys: [String], in value: Any) -> [Any]? {
        guard let dict = value as? [String: Any] else {
            if let array = value as? [Any] {
                for item in array {
                    if let found = self.findFirstArray(forKeys: keys, in: item) {
                        return found
                    }
                }
            }
            return nil
        }
        for key in keys {
            if let array = dict[key] as? [Any] {
                return array
            }
        }
        for nested in dict.values {
            if let found = self.findFirstArray(forKeys: keys, in: nested) {
                return found
            }
        }
        return nil
    }

    private static func findFirstInt(forKeys keys: [String], in value: Any) -> Int? {
        if let dict = value as? [String: Any] {
            for key in keys {
                if let parsed = self.parseInt(dict[key]) {
                    return parsed
                }
            }
            for nested in dict.values {
                if let parsed = self.findFirstInt(forKeys: keys, in: nested) {
                    return parsed
                }
            }
            return nil
        }
        if let array = value as? [Any] {
            for item in array {
                if let parsed = self.findFirstInt(forKeys: keys, in: item) {
                    return parsed
                }
            }
        }
        return nil
    }

    private static func findFirstString(forKeys keys: [String], in value: Any) -> String? {
        if let dict = value as? [String: Any] {
            for key in keys {
                if let parsed = self.parseString(dict[key]) {
                    return parsed
                }
            }
            for nested in dict.values {
                if let parsed = self.findFirstString(forKeys: keys, in: nested) {
                    return parsed
                }
            }
            return nil
        }
        if let array = value as? [Any] {
            for item in array {
                if let parsed = self.findFirstString(forKeys: keys, in: item) {
                    return parsed
                }
            }
        }
        return nil
    }

    private static func findFirstDate(forKeys keys: [String], in value: Any) -> Date? {
        if let dict = value as? [String: Any] {
            for key in keys {
                if let parsed = self.parseDate(dict[key]) {
                    return parsed
                }
            }
            for nested in dict.values {
                if let parsed = self.findFirstDate(forKeys: keys, in: nested) {
                    return parsed
                }
            }
            return nil
        }
        if let array = value as? [Any] {
            for item in array {
                if let parsed = self.findFirstDate(forKeys: keys, in: item) {
                    return parsed
                }
            }
        }
        return nil
    }

    private static func expandedJSON(_ value: Any) -> Any {
        OneConsoleJSON.expandEmbeddedJSON(value)
    }

    private static func anyInt(for keys: [String], in dict: [String: Any]) -> Int? {
        for key in keys {
            if let value = OneConsoleJSON.int(dict[key]) {
                return value
            }
        }
        return nil
    }

    private static func anyString(for keys: [String], in dict: [String: Any]) -> String? {
        for key in keys {
            if let value = OneConsoleJSON.string(dict[key]) {
                return value
            }
        }
        return nil
    }

    private static func anyDate(for keys: [String], in dict: [String: Any]) -> Date? {
        for key in keys {
            if let value = OneConsoleJSON.date(dict[key]) {
                return value
            }
        }
        return nil
    }

    private static func anyPercent(for keys: [String], in dict: [String: Any]) -> Double? {
        for key in keys {
            if let value = self.parsePercent(dict[key]) {
                return value
            }
        }
        return nil
    }

    private static func anyBool(for keys: [String], in dict: [String: Any]) -> Bool? {
        for key in keys {
            if let value = self.parseBool(dict[key]) {
                return value
            }
        }
        return nil
    }

    private static func findFirstPercent(forKeys keys: [String], in value: Any) -> Double? {
        if let dict = value as? [String: Any] {
            for key in keys {
                if let parsed = self.parsePercent(dict[key]) {
                    return parsed
                }
            }
            for nested in dict.values {
                if let parsed = self.findFirstPercent(forKeys: keys, in: nested) {
                    return parsed
                }
            }
            return nil
        }
        if let array = value as? [Any] {
            for item in array {
                if let parsed = self.findFirstPercent(forKeys: keys, in: item) {
                    return parsed
                }
            }
        }
        return nil
    }

    private static func parseDate(_ raw: Any?) -> Date? {
        OneConsoleJSON.date(raw)
    }

    private static func parseInt(_ raw: Any?) -> Int? {
        OneConsoleJSON.int(raw)
    }

    private static func parseString(_ raw: Any?) -> String? {
        OneConsoleJSON.string(raw)
    }

    private static func parsePercent(_ raw: Any?) -> Double? {
        if let intValue = self.parseInt(raw) {
            return max(0, min(Double(intValue), 100))
        }
        guard let rawString = self.parseString(raw) else { return nil }
        let cleaned = rawString
            .replacingOccurrences(of: "%", with: "")
            .trimmingCharacters(in: .whitespacesAndNewlines)
        guard let parsed = Double(cleaned) else { return nil }
        return max(0, min(parsed, 100))
    }

    private static func parseBool(_ raw: Any?) -> Bool? {
        if let value = raw as? Bool {
            return value
        }
        if let number = raw as? NSNumber {
            return number.boolValue
        }
        guard let string = self.parseString(raw)?.lowercased() else { return nil }
        switch string {
        case "true", "1", "yes", "active", "valid":
            return true
        case "false", "0", "no", "inactive", "invalid", "expired":
            return false
        default:
            return nil
        }
    }

    private static func matchFirstGroup(pattern: String, in text: String) -> String? {
        guard let regex = try? NSRegularExpression(pattern: pattern, options: []) else {
            return nil
        }
        let range = NSRange(text.startIndex..<text.endIndex, in: text)
        guard let match = regex.firstMatch(in: text, options: [], range: range),
              match.numberOfRanges > 1,
              let valueRange = Range(match.range(at: 1), in: text)
        else {
            return nil
        }
        let value = text[valueRange].trimmingCharacters(in: .whitespacesAndNewlines)
        return value.isEmpty ? nil : String(value)
    }

    private static func extractConsoleSECToken(from html: String) -> String? {
        let patterns = [
            #"SEC_TOKEN\s*:\s*\"([^\"]+)\""#,
            #"SEC_TOKEN\s*:\s*'([^']+)'"#,
            #"secToken\s*:\s*\"([^\"]+)\""#,
            #"sec_token\s*:\s*\"([^\"]+)\""#,
            #"sec_token\s*:\s*'([^']+)'"#,
            #"\"SEC_TOKEN\"\s*:\s*\"([^\"]+)\""#,
            #"\"sec_token\"\s*:\s*\"([^\"]+)\""#,
        ]

        for pattern in patterns {
            if let token = self.matchFirstGroup(pattern: pattern, in: html), !token.isEmpty {
                return token
            }
        }
        return nil
    }

    private static func extractCookieValue(name: String, from cookieHeader: String) -> String? {
        let segments = cookieHeader.split(separator: ";")
        for segment in segments {
            let part = segment.trimmingCharacters(in: .whitespacesAndNewlines)
            guard let index = part.firstIndex(of: "=") else { continue }
            let key = String(part[..<index]).trimmingCharacters(in: .whitespacesAndNewlines)
            if key == name {
                let value = String(part[part.index(after: index)...]).trimmingCharacters(in: .whitespacesAndNewlines)
                return value.isEmpty ? nil : value
            }
        }
        return nil
    }
}

public enum AlibabaCodingPlanUsageError: LocalizedError, Sendable, Equatable {
    case loginRequired
    case invalidCredentials
    case networkError(String)
    case apiError(String)
    case parseFailed(String)
    case apiKeyUnavailableInRegion

    var shouldRetryOnAlternateRegion: Bool {
        switch self {
        case .loginRequired:
            true
        case .invalidCredentials:
            true
        case .apiKeyUnavailableInRegion:
            false
        case let .apiError(message):
            message.contains("HTTP 404") || message.contains("HTTP 403")
        case let .parseFailed(message):
            message.contains("Missing coding plan quota data") || message.contains("No quota windows found")
        case .networkError:
            false
        }
    }

    public var errorDescription: String? {
        switch self {
        case .loginRequired:
            "Alibaba Coding Plan console login is required. " +
                "Sign in to Model Studio/Bailian in a supported browser or paste a Cookie header."
        case .invalidCredentials:
            "Alibaba Coding Plan API credentials are invalid or expired."
        case .apiKeyUnavailableInRegion:
            "Alibaba Coding Plan quota is not available through Coding Plan API keys for this account/region. " +
                "Use cookie authentication in Settings -> Providers -> Alibaba if the Alibaba console exposes a " +
                "compatible session, or switch regions if quota API access is available there."
        case let .networkError(message):
            "Alibaba Coding Plan network error: \(message)"
        case let .apiError(message):
            "Alibaba Coding Plan API error: \(message)"
        case let .parseFailed(message):
            "Failed to parse Alibaba Coding Plan response: \(message)"
        }
    }
}

// swiftlint:enable type_body_length
