import Foundation

extension Decimal {
    // MARK: - Performance: Shared formatters (avoid creating on every call)
    private static let percentFormatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .percent
        formatter.maximumFractionDigits = 2
        formatter.multiplier = 1
        return formatter
    }()

    private static let decimalFormatter: NumberFormatter = {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.maximumFractionDigits = 2
        return formatter
    }()

    // MARK: - Performance: Cached currency symbol
    private static var _cachedCurrencySymbol: String?
    private static var currencySymbolCacheTime: Date?

    private static var cachedCurrencySymbol: String {
        // Refresh cache every 60 seconds to pick up settings changes
        let now = Date()
        if let cached = _cachedCurrencySymbol,
           let cacheTime = currencySymbolCacheTime,
           now.timeIntervalSince(cacheTime) < 60 {
            return cached
        }
        let symbol = AppSettings.getOrCreate(in: CoreDataStack.shared.viewContext).currencySymbol
        _cachedCurrencySymbol = symbol
        currencySymbolCacheTime = now
        return symbol
    }

    /// Call this when currency settings change to invalidate the cache
    static func invalidateCurrencyCache() {
        _cachedCurrencySymbol = nil
        currencySymbolCacheTime = nil
    }

    // MARK: - Formatting

    var currencyString: String {
        CurrencyFormatter.format(self, style: .currency, maximumFractionDigits: 2)
    }

    var compactCurrencyString: String {
        CurrencyFormatter.format(self, style: .currency, maximumFractionDigits: 0)
    }

    var shortCurrencyString: String {
        let value = NSDecimalNumber(decimal: self).doubleValue
        let symbol = Self.cachedCurrencySymbol

        switch Swift.abs(value) {
        case 1_000_000...:
            return String(format: "%@%.1fM", symbol, value / 1_000_000)
        case 1_000...:
            return String(format: "%@%.1fK", symbol, value / 1_000)
        default:
            return compactCurrencyString
        }
    }

    var percentageString: String {
        Self.percentFormatter.string(from: self as NSDecimalNumber) ?? "0%"
    }

    var signedPercentageString: String {
        let prefix = self >= 0 ? "+" : ""
        return prefix + percentageString
    }

    var decimalString: String {
        Self.decimalFormatter.string(from: self as NSDecimalNumber) ?? "0"
    }

    // MARK: - Conversions

    var doubleValue: Double {
        NSDecimalNumber(decimal: self).doubleValue
    }

    var intValue: Int {
        NSDecimalNumber(decimal: self).intValue
    }

    // MARK: - Math Operations

    var abs: Decimal {
        self < 0 ? -self : self
    }

    func rounded(scale: Int = 2) -> Decimal {
        var result = Decimal()
        var mutableSelf = self
        NSDecimalRound(&result, &mutableSelf, scale, .plain)
        return result
    }

    // MARK: - Comparisons

    var isPositive: Bool {
        self > 0
    }

    var isNegative: Bool {
        self < 0
    }

    var isZero: Bool {
        self == 0
    }

    // MARK: - Static Helpers

    static func from(_ double: Double) -> Decimal {
        Decimal(double)
    }

    static func from(_ string: String) -> Decimal? {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        return formatter.number(from: string)?.decimalValue
    }
}

// MARK: - NSDecimalNumber Extension

extension NSDecimalNumber {
    var currencyString: String {
        decimalValue.currencyString
    }

    var compactCurrencyString: String {
        decimalValue.compactCurrencyString
    }
}

// MARK: - Optional Decimal

extension Optional where Wrapped == Decimal {
    var orZero: Decimal {
        self ?? Decimal.zero
    }

    var currencyString: String {
        (self ?? Decimal.zero).currencyString
    }
}
