import Foundation

// MARK: - Tier Status (from tierStatus.cfm)

struct TierStatus: Codable {
    var tier: Int
    var stripe: StripeInfo
    var activation: ActivationInfo

    enum CodingKeys: String, CodingKey {
        case tier = "TIER"
        case stripe = "STRIPE"
        case activation = "ACTIVATION"
    }

    init(tier: Int = 0, stripe: StripeInfo = StripeInfo(), activation: ActivationInfo = ActivationInfo()) {
        self.tier = tier
        self.stripe = stripe
        self.activation = activation
    }

    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        tier = (try? c.decode(Int.self, forKey: .tier)) ?? 0
        stripe = (try? c.decode(StripeInfo.self, forKey: .stripe)) ?? StripeInfo()
        activation = (try? c.decode(ActivationInfo.self, forKey: .activation)) ?? ActivationInfo()
    }

    struct StripeInfo: Codable {
        var hasAccount: Bool
        var payoutsEnabled: Bool
        var setupIncomplete: Bool

        enum CodingKeys: String, CodingKey {
            case hasAccount = "HasAccount"
            case payoutsEnabled = "PayoutsEnabled"
            case setupIncomplete = "SetupIncomplete"
        }

        init(hasAccount: Bool = false, payoutsEnabled: Bool = false, setupIncomplete: Bool = false) {
            self.hasAccount = hasAccount
            self.payoutsEnabled = payoutsEnabled
            self.setupIncomplete = setupIncomplete
        }

        init(from decoder: Decoder) throws {
            let c = try decoder.container(keyedBy: CodingKeys.self)
            hasAccount = (try? c.decode(Bool.self, forKey: .hasAccount)) ?? false
            payoutsEnabled = (try? c.decode(Bool.self, forKey: .payoutsEnabled)) ?? false
            setupIncomplete = (try? c.decode(Bool.self, forKey: .setupIncomplete)) ?? false
        }
    }

    struct ActivationInfo: Codable {
        var balanceCents: Int
        var capCents: Int
        var remainingCents: Int
        var isComplete: Bool
        var progressPercent: Int

        enum CodingKeys: String, CodingKey {
            case balanceCents = "BalanceCents"
            case capCents = "CapCents"
            case remainingCents = "RemainingCents"
            case isComplete = "IsComplete"
            case progressPercent = "ProgressPercent"
        }

        init(balanceCents: Int = 0, capCents: Int = 2500, remainingCents: Int = 2500, isComplete: Bool = false, progressPercent: Int = 0) {
            self.balanceCents = balanceCents
            self.capCents = capCents
            self.remainingCents = remainingCents
            self.isComplete = isComplete
            self.progressPercent = progressPercent
        }

        init(from decoder: Decoder) throws {
            let c = try decoder.container(keyedBy: CodingKeys.self)
            balanceCents = (try? c.decode(Int.self, forKey: .balanceCents)) ?? 0
            capCents = (try? c.decode(Int.self, forKey: .capCents)) ?? 2500
            remainingCents = (try? c.decode(Int.self, forKey: .remainingCents)) ?? 2500
            isComplete = (try? c.decode(Bool.self, forKey: .isComplete)) ?? false
            progressPercent = (try? c.decode(Int.self, forKey: .progressPercent)) ?? 0
        }

        var balanceDollars: String {
            String(format: "$%.2f", Double(balanceCents) / 100.0)
        }

        var capDollars: String {
            String(format: "$%.2f", Double(capCents) / 100.0)
        }

        var progress: Double {
            guard capCents > 0 else { return 0 }
            return Double(balanceCents) / Double(capCents)
        }
    }
}

// MARK: - Ledger Response (from ledger.cfm)

struct LedgerResponse: Codable {
    var entries: [LedgerEntry]
    var totals: LedgerTotals

    enum CodingKeys: String, CodingKey {
        case entries = "ENTRIES"
        case totals = "TOTALS"
    }

    init(entries: [LedgerEntry] = [], totals: LedgerTotals = LedgerTotals()) {
        self.entries = entries
        self.totals = totals
    }

    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        entries = (try? c.decode([LedgerEntry].self, forKey: .entries)) ?? []
        totals = (try? c.decode(LedgerTotals.self, forKey: .totals)) ?? LedgerTotals()
    }
}

struct LedgerEntry: Codable, Identifiable {
    let id: Int
    let taskId: Int
    let grossEarningsCents: Int
    let activationWithheldCents: Int
    let netTransferCents: Int
    let status: String
    let createdAt: String

    enum CodingKeys: String, CodingKey {
        case id = "ID"
        case taskId = "TaskID"
        case grossEarningsCents = "GrossEarningsCents"
        case activationWithheldCents = "ActivationWithheldCents"
        case netTransferCents = "NetTransferCents"
        case status = "Status"
        case createdAt = "CreatedAt"
    }

    var grossDollars: String {
        String(format: "$%.2f", Double(grossEarningsCents) / 100.0)
    }

    var netDollars: String {
        String(format: "$%.2f", Double(netTransferCents) / 100.0)
    }

    var withheldDollars: String {
        String(format: "$%.2f", Double(activationWithheldCents) / 100.0)
    }

    var statusDisplay: String {
        switch status {
        case "pending_charge": return "Pending"
        case "charged": return "Charged"
        case "transferred": return "Transferred"
        case "reversed": return "Reversed"
        default: return status.capitalized
        }
    }
}

struct LedgerTotals: Codable {
    var totalGrossCents: Int
    var totalWithheldCents: Int
    var totalNetCents: Int

    enum CodingKeys: String, CodingKey {
        case totalGrossCents = "TotalGrossCents"
        case totalWithheldCents = "TotalWithheldCents"
        case totalNetCents = "TotalNetCents"
    }

    init(totalGrossCents: Int = 0, totalWithheldCents: Int = 0, totalNetCents: Int = 0) {
        self.totalGrossCents = totalGrossCents
        self.totalWithheldCents = totalWithheldCents
        self.totalNetCents = totalNetCents
    }

    init(from decoder: Decoder) throws {
        let c = try decoder.container(keyedBy: CodingKeys.self)
        totalGrossCents = (try? c.decode(Int.self, forKey: .totalGrossCents)) ?? 0
        totalWithheldCents = (try? c.decode(Int.self, forKey: .totalWithheldCents)) ?? 0
        totalNetCents = (try? c.decode(Int.self, forKey: .totalNetCents)) ?? 0
    }

    var totalGrossDollars: String {
        String(format: "$%.2f", Double(totalGrossCents) / 100.0)
    }

    var totalNetDollars: String {
        String(format: "$%.2f", Double(totalNetCents) / 100.0)
    }
}
