//
//  StatisticsModels.swift
//  suixinkan
//
//  Created by Codex on 2026/6/22.
//

import Foundation

/// 数据统计时间段实体，表示看板顶部的快捷日期范围。
enum StatisticsPeriod: String, CaseIterable, Identifiable {
    case today = "今日"
    case yesterday = "昨日"
    case sevenDays = "7日"
    case thisMonth = "本月"

    var id: String { rawValue }

    /// 后端汇总接口需要的范围标识。
    var apiRange: String {
        switch self {
        case .today:
            return "1"
        case .yesterday:
            return "2"
        case .sevenDays:
            return "3"
        case .thisMonth:
            return "4"
        }
    }

    /// 当前时间段对应的本地日期区间。
    var interval: (start: Date, end: Date) {
        let calendar = Calendar.current
        let today = calendar.startOfDay(for: Date())
        switch self {
        case .today:
            return (today, today)
        case .yesterday:
            let day = calendar.date(byAdding: .day, value: -1, to: today) ?? today
            return (day, day)
        case .sevenDays:
            return (calendar.date(byAdding: .day, value: -6, to: today) ?? today, today)
        case .thisMonth:
            let components = calendar.dateComponents([.year, .month], from: today)
            return (calendar.date(from: components) ?? today, today)
        }
    }

    /// 页面展示的时间范围文案。
    var selectedTimeText: String {
        let dates = interval
        return "\(Self.uiDateFormatter.string(from: dates.start))至\(Self.uiDateFormatter.string(from: dates.end))"
    }

    /// 后端列表接口开始日期。
    var apiStartTime: String {
        Self.apiDateFormatter.string(from: interval.start)
    }

    /// 后端列表接口结束日期。
    var apiEndTime: String {
        Self.apiDateFormatter.string(from: interval.end)
    }

    private static let uiDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "zh_CN")
        formatter.dateFormat = "yyyy/MM/dd"
        return formatter
    }()

    private static let apiDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
}

/// 数据统计汇总实体，表示订单金额、数量、客单价、实收和退款。
struct StatisticsSummaryResponse: Decodable, Equatable {
    let orderAmountSum: String
    let orderCount: Int
    let orderPriceAverage: String
    let receivedAmountSum: String
    let refundAmountSum: String

    var orderAmountValue: Double { Self.parseAmount(orderAmountSum) }
    var orderPriceAverageValue: Double { Self.parseAmount(orderPriceAverage) }
    var receivedAmountValue: Double { Self.parseAmount(receivedAmountSum) }
    var refundAmountValue: Double { Self.parseAmount(refundAmountSum) }

    enum CodingKeys: String, CodingKey {
        case orderAmountSum = "order_amount_sum"
        case orderCount = "order_count"
        case orderPriceAverage = "order_price_avg"
        case receivedAmountSum = "received_amount_sum"
        case refundAmountSum = "refund_amount_sum"
    }

    /// 创建统计汇总实体，主要用于初始状态和测试。
    init(
        orderAmountSum: String = "",
        orderCount: Int = 0,
        orderPriceAverage: String = "",
        receivedAmountSum: String = "",
        refundAmountSum: String = ""
    ) {
        self.orderAmountSum = orderAmountSum
        self.orderCount = orderCount
        self.orderPriceAverage = orderPriceAverage
        self.receivedAmountSum = receivedAmountSum
        self.refundAmountSum = refundAmountSum
    }

    /// 宽松解码统计汇总字段。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        orderAmountSum = try container.decodeLossyString(forKey: .orderAmountSum)
        orderCount = try container.decodeLossyInt(forKey: .orderCount) ?? 0
        orderPriceAverage = try container.decodeLossyString(forKey: .orderPriceAverage)
        receivedAmountSum = try container.decodeLossyString(forKey: .receivedAmountSum)
        refundAmountSum = try container.decodeLossyString(forKey: .refundAmountSum)
    }

    private static func parseAmount(_ text: String) -> Double {
        let normalized = text.filter { "0123456789.-".contains($0) }
        return Double(normalized) ?? 0
    }
}

/// 每日统计实体，表示某天订单数、客单价、退款和实收。
struct StatisticsDailyItem: Decodable, Identifiable, Equatable {
    var id: String { date }

    let date: String
    let orderCount: Int
    let orderPrice: String
    let refund: String
    let received: String

    var orderPriceValue: Double { Self.parseAmount(orderPrice) }
    var refundValue: Double { Self.parseAmount(refund) }
    var receivedValue: Double { Self.parseAmount(received) }

    enum CodingKeys: String, CodingKey {
        case date
        case orderCount = "order_count"
        case orderPrice = "order_price"
        case refund
        case received
    }

    /// 宽松解码每日统计字段。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        date = try container.decodeLossyString(forKey: .date)
        orderCount = try container.decodeLossyInt(forKey: .orderCount) ?? 0
        orderPrice = try container.decodeLossyString(forKey: .orderPrice)
        refund = try container.decodeLossyString(forKey: .refund)
        received = try container.decodeLossyString(forKey: .received)
    }

    private static func parseAmount(_ text: String) -> Double {
        let normalized = text.filter { "0123456789.-".contains($0) }
        return Double(normalized) ?? 0
    }
}

private extension KeyedDecodingContainer {
    /// 将任意常见 JSON 值宽松解码成字符串。
    func decodeLossyString(forKey key: Key) throws -> String {
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return String(value)
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return String(value)
        }
        return ""
    }

    /// 将 Int、Double 或数字字符串宽松解码成整数。
    func decodeLossyInt(forKey key: Key) throws -> Int? {
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
            if let intValue = Int(text) {
                return intValue
            }
            if let doubleValue = Double(text) {
                return Int(doubleValue)
            }
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return Int(value)
        }
        return nil
    }
}
