import Foundation

/// Форматирование рыночных значений.
///
/// `NumberFormatter`/`DateFormatter` дороги в создании, поэтому все экземпляры
/// кэшируются (чтение форматтеров потокобезопасно начиная с macOS 10.9).
enum MarketFormatting {

    // MARK: - Публичное API

    /// Цена с точностью, зависящей от порядка величины:
    /// «70 324,00», «90,0800», «0,338200».
    static func price(_ value: Double) -> String {
        priceFormatter(for: value).string(from: NSNumber(value: value))
            ?? String(format: "%.2f", value)
    }

    /// Абсолютное изменение со знаком: «+1 676,00».
    static func signedAmount(_ value: Double) -> String {
        let formatter = abs(value) >= 100 ? signedTwoDigits : signedFourDigits
        return formatter.string(from: NSNumber(value: value))
            ?? String(format: "%+.2f", value)
    }

    /// Доля → проценты: 0.0234 → «2.34%» или «+2.34%».
    static func percent(_ share: Double, signed: Bool) -> String {
        String(format: signed ? "%+.2f%%" : "%.2f%%", share * 100)
    }

    /// Метка обновления: «27 октября 17:10» или «17:10».
    static func updated(_ date: Date, withDate: Bool) -> String {
        (withDate ? dateTime : timeOnly).string(from: date)
    }

    // MARK: - Кэш форматтеров

    private static let priceTwoDigits = decimal(maxFraction: 2)
    private static let priceFourDigits = decimal(maxFraction: 4)
    private static let priceSixDigits = decimal(maxFraction: 6)
    private static let signedTwoDigits = decimal(maxFraction: 2, signed: true)
    private static let signedFourDigits = decimal(maxFraction: 4, signed: true)

    private static func priceFormatter(for value: Double) -> NumberFormatter {
        switch abs(value) {
        case 1000...: priceTwoDigits
        case 1...: priceFourDigits
        default: priceSixDigits
        }
    }

    private static func decimal(maxFraction: Int, signed: Bool = false) -> NumberFormatter {
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.minimumFractionDigits = 2
        formatter.maximumFractionDigits = maxFraction
        if signed {
            formatter.positivePrefix = formatter.plusSign
        }
        return formatter
    }

    private static let dateTime = dateFormatter("d MMMM HH:mm")
    private static let timeOnly = dateFormatter("HH:mm")

    private static func dateFormatter(_ format: String) -> DateFormatter {
        let formatter = DateFormatter()
        formatter.locale = .current
        formatter.dateFormat = format
        return formatter
    }
}
