//
//  ScheduleModels.swift
//  suixinkan
//
//  Created by Codex on 2026/6/24.
//

import Foundation

/// 排班日程实体，表示某一天的一条工作安排。
struct ScheduleItem: Decodable, Identifiable, Hashable {
    let id: Int
    let name: String
    let remark: String
    let startTime: String
    let endTime: String
    let scheduleDate: String
    let orderNumber: String?
    let userNickname: String?
    let userPhone: String?
    let orderStatus: Int?
    let orderStatusName: String?

    /// 字段映射，兼容后端下划线命名。
    enum CodingKeys: String, CodingKey {
        case id
        case name
        case remark
        case startTime = "start_time"
        case endTime = "end_time"
        case scheduleDate = "schedule_date"
        case orderNumber = "order_number"
        case userNickname = "user_nickname"
        case userPhone = "user_phone"
        case orderStatus = "order_status"
        case orderStatusName = "order_status_name"
    }

    /// 宽松解码排班字段。
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        id = try container.decodeScheduleLossyInt(forKey: .id) ?? 0
        name = try container.decodeScheduleLossyString(forKey: .name)
        remark = try container.decodeScheduleLossyString(forKey: .remark)
        startTime = try container.decodeScheduleLossyString(forKey: .startTime)
        endTime = try container.decodeScheduleLossyString(forKey: .endTime)
        scheduleDate = try container.decodeScheduleLossyString(forKey: .scheduleDate)
        orderNumber = container.decodeScheduleLossyOptionalString(forKey: .orderNumber)
        userNickname = container.decodeScheduleLossyOptionalString(forKey: .userNickname)
        userPhone = container.decodeScheduleLossyOptionalString(forKey: .userPhone)
        orderStatus = try container.decodeScheduleLossyInt(forKey: .orderStatus)
        orderStatusName = container.decodeScheduleLossyOptionalString(forKey: .orderStatusName)
    }
}

/// 新增排班请求实体。
struct AddScheduleRequest: Encodable, Equatable {
    let scenicId: String
    let name: String
    let remark: String
    let startTime: String
    let endTime: String
    let scheduleDate: String
    let orderNumber: String?

    /// 请求字段映射，兼容后端下划线命名。
    enum CodingKeys: String, CodingKey {
        case scenicId = "scenic_id"
        case name
        case remark
        case startTime = "start_time"
        case endTime = "end_time"
        case scheduleDate = "schedule_date"
        case orderNumber = "order_number"
    }
}

/// 删除排班请求实体。
struct ScheduleDeleteRequest: Encodable, Equatable {
    let id: Int
}

/// 排班编辑表单实体，用于 ViewModel 校验和生成请求。
struct ScheduleDraft: Equatable {
    var name = ""
    var remark = ""
    var scheduleDate = ""
    var startTime = ""
    var endTime = ""
    var manualOrderNumber = ""
    var selectedOrder: AvailableOrderResponse?

    /// 计算最终订单号，优先使用选择的订单，手工输入作为兜底。
    func finalOrderNumber() -> String? {
        let picked = selectedOrder?.orderNumber.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        let manual = manualOrderNumber.trimmingCharacters(in: .whitespacesAndNewlines)
        let value = picked.isEmpty ? manual : picked
        return value.isEmpty ? nil : value
    }
}

private extension KeyedDecodingContainer {
    /// 将 String、数字和 Bool 宽松解码为字符串。
    func decodeScheduleLossyString(forKey key: Key) throws -> String {
        decodeScheduleLossyOptionalString(forKey: key) ?? ""
    }

    /// 将 String、数字和 Bool 宽松解码为可选字符串。
    func decodeScheduleLossyOptionalString(forKey key: Key) -> String? {
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let trimmed = value.trimmingCharacters(in: .whitespacesAndNewlines)
            return trimmed.isEmpty ? nil : 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)
        }
        if let value = try? decodeIfPresent(Bool.self, forKey: key) {
            return value ? "1" : "0"
        }
        return nil
    }

    /// 将 String、Double 和 Int 宽松解码为 Int。
    func decodeScheduleLossyInt(forKey key: Key) throws -> Int? {
        if let value = try? decodeIfPresent(Int.self, forKey: key) {
            return value
        }
        if let value = try? decodeIfPresent(Double.self, forKey: key) {
            return Int(value)
        }
        if let value = try? decodeIfPresent(String.self, forKey: key) {
            let text = value.trimmingCharacters(in: .whitespacesAndNewlines)
            return Int(text) ?? Double(text).map(Int.init)
        }
        return nil
    }
}
