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

import Foundation
import Combine

@MainActor
/// 订单页面 ViewModel，管理订单列表、核销列表、筛选条件和手动核销流程。
final class OrdersViewModel: ObservableObject {
    @Published var selectedEntry: OrdersEntry = .storeOrders
    @Published var selectedStatus = 0
    @Published var searchPhone = ""
    @Published var filterStartDate: Date?
    @Published var filterEndDate: Date?
    @Published private(set) var loading = false
    @Published private(set) var loadingMore = false
    @Published private(set) var isVerifying = false
    @Published private(set) var currentVerifyingOrderNumber: String?

    @Published private(set) var storeOrders: [OrderEntity] = []
    @Published private(set) var storeTotal = 0
    @Published private(set) var storePage = 1
    @Published private(set) var storeHasMore = false

    @Published private(set) var writeOffOrders: [WriteOffOrderItem] = []
    @Published private(set) var writeOffTotal = 0
    @Published private(set) var writeOffPage = 1
    @Published private(set) var writeOffHasMore = false

    @Published var orderSourcePeople: [OrderSourcePerson] = []
    @Published var orderSourceLeads: [String: [OrderSourceLead]] = [:]
    @Published var orderSourceSelections: [String: OrderSourceSelection] = [:]
    @Published var loadingOrderSourceLeadsFor: String?

    @Published var refundingOrder: OrderEntity?
    @Published var sendGiftContext: SendGiftContext?

    private var loadingOrderSourcePeople = false

    /// 赠送修图/视频弹窗上下文。
    struct SendGiftContext: Equatable, Identifiable {
        var id: String { orderNumber }
        let orderNumber: String
        let nowPhotoNum: Int
        let nowVideoNum: Int
        var sendPhotoNum: Int
        var sendVideoNum: Int
    }

    static let orderTypePhotographerFollow = 11
    static let orderTypePhotographerFollowOfflineScan = 14

    /// 返回去除首尾空白后的手机号搜索值。
    var normalizedPhone: String? {
        let text = searchPhone.trimmingCharacters(in: .whitespacesAndNewlines)
        return text.isEmpty ? nil : text
    }

    /// 根据当前子入口刷新对应列表。
    func reload(api: OrderServing, scenicId: Int?, storeId: Int? = nil, appRole: AppRoleCode?, showLoading: Bool = true) async throws {
        switch selectedEntry {
        case .storeOrders:
            try await reloadStoreOrders(api: api, scenicId: scenicId, appRole: appRole, showLoading: showLoading)
        case .verificationOrders:
            try await reloadWriteOffOrders(api: api, scenicId: scenicId, storeId: storeId, showLoading: showLoading)
        }
    }

    /// 刷新订单管理列表，缺少景区时清空旧数据。
    func reloadStoreOrders(api: OrderServing, scenicId: Int?, appRole: AppRoleCode?, showLoading: Bool = true) async throws {
        guard let scenicId else {
            storeOrders = []
            storeTotal = 0
            storePage = 1
            storeHasMore = false
            return
        }

        if showLoading { loading = true }
        defer { if showLoading { loading = false } }

        let result = try await api.orderList(
            scenicId: scenicId,
            page: 1,
            pageSize: pageSize,
            orderStatus: orderStatusQuery,
            userPhone: normalizedPhone,
            startTime: startTimeQuery,
            endTime: endTimeQuery,
            isRefined: refinedQuery,
            isScenicAdmin: appRole?.isScenicAdmin == true
        )
        storeOrders = result.list
        storeTotal = result.total
        storePage = 1
        storeHasMore = storeOrders.count < result.total && !result.list.isEmpty
        syncOrderSourceSelections(from: result.list)
    }

    /// 加载订单管理下一页。
    func loadMoreStoreOrders(api: OrderServing, scenicId: Int?, appRole: AppRoleCode?) async throws {
        guard !loadingMore, storeHasMore, let scenicId else { return }
        loadingMore = true
        defer { loadingMore = false }

        let nextPage = storePage + 1
        let result = try await api.orderList(
            scenicId: scenicId,
            page: nextPage,
            pageSize: pageSize,
            orderStatus: orderStatusQuery,
            userPhone: normalizedPhone,
            startTime: startTimeQuery,
            endTime: endTimeQuery,
            isRefined: refinedQuery,
            isScenicAdmin: appRole?.isScenicAdmin == true
        )
        storeOrders.append(contentsOf: result.list)
        storeTotal = result.total
        storePage = nextPage
        storeHasMore = storeOrders.count < result.total && !result.list.isEmpty
    }

    /// 刷新核销订单列表，缺少景区时清空旧数据。
    func reloadWriteOffOrders(api: OrderServing, scenicId: Int?, storeId: Int? = nil, showLoading: Bool = true) async throws {
        guard let scenicId else {
            writeOffOrders = []
            writeOffTotal = 0
            writeOffPage = 1
            writeOffHasMore = false
            return
        }

        if showLoading { loading = true }
        defer { if showLoading { loading = false } }

        let result = try await api.writeOffList(
            scenicId: scenicId,
            storeId: storeId,
            page: 1,
            pageSize: pageSize,
            orderStatus: nil,
            orderVerifyStatus: nil,
            startTime: nil,
            endTime: nil,
            userPhone: nil
        )
        writeOffOrders = result.list
        writeOffTotal = result.total
        writeOffPage = 1
        writeOffHasMore = writeOffOrders.count < result.total && !result.list.isEmpty
    }

    /// 加载核销订单下一页。
    func loadMoreWriteOffOrders(api: OrderServing, scenicId: Int?, storeId: Int? = nil) async throws {
        guard !loadingMore, writeOffHasMore, let scenicId else { return }
        loadingMore = true
        defer { loadingMore = false }

        let nextPage = writeOffPage + 1
        let result = try await api.writeOffList(
            scenicId: scenicId,
            storeId: storeId,
            page: nextPage,
            pageSize: pageSize,
            orderStatus: nil,
            orderVerifyStatus: nil,
            startTime: nil,
            endTime: nil,
            userPhone: nil
        )
        writeOffOrders.append(contentsOf: result.list)
        writeOffTotal = result.total
        writeOffPage = nextPage
        writeOffHasMore = writeOffOrders.count < result.total && !result.list.isEmpty
    }

    /// 手动核销订单，并在成功后刷新核销列表。
    func verify(api: OrderServing, scenicId: Int, storeId: Int? = nil, orderNumber: String) async throws {
        guard !isVerifying else { return }

        isVerifying = true
        currentVerifyingOrderNumber = orderNumber
        defer {
            isVerifying = false
            currentVerifyingOrderNumber = nil
        }

        try await api.writeOff(orderNumber: orderNumber)
        let refreshed = try await api.writeOffList(
            scenicId: scenicId,
            storeId: storeId,
            page: 1,
            pageSize: pageSize,
            orderStatus: nil,
            orderVerifyStatus: nil,
            startTime: nil,
            endTime: nil,
            userPhone: nil
        )
        writeOffOrders = refreshed.list
        writeOffTotal = refreshed.total
        writeOffPage = 1
        writeOffHasMore = writeOffOrders.count < refreshed.total && !refreshed.list.isEmpty
    }

    /// 判断订单卡片是否展示退款按钮。
    func shouldShowRefundButton(order: OrderEntity, appRole: AppRoleCode?) -> Bool {
        guard !Self.isScenicAdminReadOnly(appRole: appRole) else { return false }
        return (order.orderStatus == 18 || order.orderStatus == 30) && order.orderType != 19
    }

    /// 判断订单卡片是否展示核销按钮。
    func shouldShowVerifyButton(order: OrderEntity, appRole: AppRoleCode?) -> Bool {
        guard !Self.isScenicAdminReadOnly(appRole: appRole) else { return false }
        if order.orderType == 19 { return true }
        guard let photoTravel = order.photoTravel else { return false }
        return photoTravel.needCheckIn && order.orderStatus != 30
    }

    /// 更新订单精修选择并同步本地列表状态。
    func updateRefinedChoice(api: OrderServing, orderNumber: String, isRefined: Int) async throws {
        try await api.updateRefinedChoice(orderNumber: orderNumber, isRefined: isRefined)
        if let index = storeOrders.firstIndex(where: { $0.orderNumber == orderNumber }) {
            storeOrders[index].isRefined = isRefined
        }
    }

    /// 取消订单并刷新列表。
    func cancelOrder(api: OrderServing, scenicId: Int?, appRole: AppRoleCode?, orderNumber: String) async throws {
        try await api.cancelOrder(orderNumber: orderNumber)
        try await reloadStoreOrders(api: api, scenicId: scenicId, appRole: appRole, showLoading: false)
    }

    /// 打开赠送修图/视频弹窗。
    func prepareSendGift(for order: OrderEntity) {
        let photoTravel = order.photoTravel
        sendGiftContext = SendGiftContext(
            orderNumber: order.orderNumber,
            nowPhotoNum: photoTravel?.orderPhotoNum ?? 0,
            nowVideoNum: photoTravel?.orderVideoNum ?? 0,
            sendPhotoNum: photoTravel?.retouchGiftPhotoNum ?? 0,
            sendVideoNum: photoTravel?.retouchGiftVideoNum ?? 0
        )
    }

    /// 提交赠送修图/视频并刷新列表。
    func submitSendGift(
        api: OrderServing,
        scenicId: Int?,
        appRole: AppRoleCode?,
        photoNum: Int,
        videoNum: Int
    ) async throws {
        guard let context = sendGiftContext else { return }
        try await api.sendGift(orderNumber: context.orderNumber, photoNum: photoNum, videoNum: videoNum)
        sendGiftContext = nil
        try await reloadStoreOrders(api: api, scenicId: scenicId, appRole: appRole, showLoading: false)
    }

    /// 当前筛选标题。
    var currentFilterTitle: String {
        OrderFilters.statusFilters.first(where: { $0.id == selectedStatus })?.title ?? "全部"
    }

    /// 判断订单卡片是否展示订单来源入口。
    func shouldShowOrderSource(order: OrderEntity, appRole: AppRoleCode?) -> Bool {
        guard !Self.isScenicAdminReadOnly(appRole: appRole) else { return false }
        return order.orderType == Self.orderTypePhotographerFollow
            || order.orderType == Self.orderTypePhotographerFollowOfflineScan
    }

    /// 景区管理员只读模式，不可操作订单来源。
    static func isScenicAdminReadOnly(appRole: AppRoleCode?) -> Bool {
        appRole?.isScenicAdmin == true
    }

    /// 获取订单已选中的订单来源。
    func getOrderSourceSelection(for order: OrderEntity) -> OrderSourceSelection? {
        orderSourceSelections[order.orderNumber] ?? order.toBoundOrderSourceSelection()
    }

    /// 从列表数据同步已绑定订单来源。
    func syncOrderSourceSelections(from orders: [OrderEntity]) {
        var updated = orderSourceSelections
        for order in orders {
            if let selection = order.toBoundOrderSourceSelection() {
                updated[order.orderNumber] = selection
            }
        }
        orderSourceSelections = updated
    }

    /// 打开订单来源 Sheet 前预加载获客员列表。
    func prepareOrderSourceSheet(api: CooperationOrderServing, storeId: Int?) async {
        orderSourceLeads = [:]
        await loadOrderSourcePeople(api: api, storeId: storeId)
    }

    /// 加载合作获客员列表供订单来源选择。
    func loadOrderSourcePeople(api: CooperationOrderServing, storeId: Int?) async {
        if loadingOrderSourcePeople { return }
        loadingOrderSourcePeople = true
        defer { loadingOrderSourcePeople = false }
        do {
            let storeParam = storeId.flatMap { $0 > 0 ? $0 : nil }
            let data = try await api.cooperativeSalers(storeId: storeParam, page: 1, pageSize: 50)
            orderSourcePeople = data.list.map { $0.toOrderSourcePerson() }
        } catch {
            orderSourcePeople = []
        }
    }

    /// 加载指定获客员的可绑定带客单。
    func loadOrderSourceLeads(api: CooperationOrderServing, person: OrderSourcePerson) async {
        if loadingOrderSourceLeadsFor == person.key { return }
        loadingOrderSourceLeadsFor = person.key
        defer { loadingOrderSourceLeadsFor = nil }
        guard let saleUserId = Int(person.key) else { return }
        do {
            let data = try await api.saleUserReferralOrders(saleUserId: saleUserId, page: 1, pageSize: 50)
            orderSourceLeads[person.key] = data.list.map { $0.toOrderSourceLead() }
        } catch {
            orderSourceLeads[person.key] = []
        }
    }

    /// 绑定订单来源带客单。
    func bindOrderSource(
        api: CooperationOrderServing,
        orderNumber: String,
        selection: OrderSourceSelection
    ) async throws {
        try await api.saleUserBindReferralOrder(
            orderNumber: orderNumber,
            referralOrderNo: selection.lead.key
        )
        orderSourceSelections[orderNumber] = selection
    }

    /// 解析扫码结果并返回当前核销列表中的匹配订单。
    func matchedWriteOffOrder(for rawCode: String) -> (orderNumber: String, matched: WriteOffOrderItem?)? {
        guard let orderNumber = OrderNumberParser.parse(rawCode) else {
            return nil
        }
        let matched = writeOffOrders.first {
            $0.orderNumber.caseInsensitiveCompare(orderNumber) == .orderedSame
        }
        return (matched?.orderNumber ?? orderNumber, matched)
    }

    /// 根据订单号查找当前核销列表中的订单。
    func writeOffOrder(matching orderNumber: String) -> WriteOffOrderItem? {
        writeOffOrders.first {
            $0.orderNumber.caseInsensitiveCompare(orderNumber) == .orderedSame
        }
    }

    /// 用于测试重复提交场景的内部状态设置。
    func markVerifyingForTests(orderNumber: String) {
        isVerifying = true
        currentVerifyingOrderNumber = orderNumber
    }

    private let pageSize = 20

    private var orderStatusQuery: Int? {
        selectedStatus > 0 ? selectedStatus : nil
    }

    private var startTimeQuery: String? {
        filterStartDate.map { Self.dayFormatter.string(from: $0) }
    }

    private var endTimeQuery: String? {
        filterEndDate.map { Self.dayFormatter.string(from: $0) }
    }

    private var refinedQuery: Int? {
        switch selectedStatus {
        case -1:
            return 1
        case -2:
            return 2
        default:
            return nil
        }
    }

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