//
//  DepositOrderListViewModel.swift
//  suixinkan
//

import Foundation

/// 店铺管理员押金单列表 ViewModel，对齐 Android `DepositOrderListViewModel`。
final class DepositOrderListViewModel {

    private(set) var searchText = ""
    private(set) var filterLabel = "全部"
    private(set) var tabIndex = 0
    private(set) var startTime: Date?
    private(set) var endTime: Date?
    private(set) var orderList: [StoreOrderItem] = []
    private(set) var isRefreshing = false
    private(set) var canLoadMore = false
    private(set) var isLoadingMore = false
    private(set) var writeOffResponse: WriteOffOrderResponse?

    var onStateChange: (() -> Void)?
    var onShowMessage: ((String) -> Void)?

    private var currentPage = 1
    private var totalCount = 0
    private var searchDebounceTask: Task<Void, Never>?

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

    func refreshOrderList(api: OrderAPI) async {
        currentPage = 1
        isRefreshing = true
        isLoadingMore = false
        notifyStateChange()
        await loadOrderList(refresh: true, api: api)
    }

    func loadMore(api: OrderAPI) async {
        guard !isLoadingMore, !isRefreshing, orderList.count < totalCount else { return }
        isLoadingMore = true
        notifyStateChange()
        await loadOrderList(refresh: false, api: api)
    }

    func shouldLoadMore(at index: Int) -> Bool {
        guard canLoadMore, !isRefreshing, !isLoadingMore else { return false }
        return index >= max(0, orderList.count - 3)
    }

    func onSearchTextChange(_ text: String, api: OrderAPI) {
        searchText = text
        notifyStateChange()
        searchDebounceTask?.cancel()
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
        if trimmed.isEmpty {
            Task { await refreshOrderList(api: api) }
            return
        }
        if Self.isValidPhone(trimmed) {
            searchDebounceTask = Task {
                try? await Task.sleep(nanoseconds: 400_000_000)
                guard !Task.isCancelled else { return }
                await refreshOrderList(api: api)
            }
        }
    }

    func onFilterChange(tab: Int) {
        tabIndex = tab
        filterLabel = StoreOrderFilter.from(tabIndex: tab).label
        notifyStateChange()
    }

    func onDateRangeSelected(start: Date?, end: Date?) {
        startTime = start
        endTime = end
        notifyStateChange()
    }

    func dismissWriteOffDialog() {
        writeOffResponse = nil
        notifyStateChange()
    }

    func processScanResult(_ scanResult: String, api: OrderAPI) async {
        guard let parsed = QRCodeScanResult.parse(scanResult) else {
            onShowMessage?("请扫描正确的二维码")
            return
        }
        guard parsed.method == "order_verify" else {
            onShowMessage?("请扫描订单核销码")
            return
        }
        guard parsed.userId > 0, !parsed.orderNumber.isEmpty, !parsed.time.isEmpty else {
            onShowMessage?("核销码内容不完整")
            return
        }
        let storeId = AppStore.shared.session.currentStoreId
        guard storeId > 0 else {
            onShowMessage?("店铺信息异常，请先选择店铺")
            return
        }
        await executeStoreOrderVerify(
            StoreOrderVerifyRequest(
                userId: parsed.userId,
                orderNumber: parsed.orderNumber,
                time: parsed.time,
                storeId: storeId
            ),
            api: api
        )
    }

    func requestRefund(
        orderNumber: String,
        refundType: Int,
        refundAmount: String,
        refundReason: String,
        api: OrderAPI
    ) async {
        let storeId = AppStore.shared.session.currentStoreId
        guard storeId > 0 else {
            onShowMessage?("店铺信息异常")
            return
        }
        do {
            try await api.storeOrderRefund(
                StoreOrderRefundRequest(
                    storeId: storeId,
                    orderNumber: orderNumber,
                    refundType: refundType,
                    refundAmount: refundAmount,
                    refundReason: refundReason
                )
            )
            onShowMessage?("退款成功")
            await refreshOrderList(api: api)
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    func canOpenDetail(for item: StoreOrderItem) -> Bool {
        item.orderType == StoreOrderType.multiTravelShoot
    }

    static func isValidPhone(_ text: String) -> Bool {
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
        guard trimmed.count == 11, trimmed.first == "1" else { return false }
        guard let second = trimmed.dropFirst().first, ("3" ... "9").contains(second) else { return false }
        return trimmed.allSatisfy(\.isNumber)
    }

    static func apiOrderStatus(forTabIndex tabIndex: Int) -> Int? {
        OrderListQueryBuilder.storeOrderStatusQuery(tabIndex: tabIndex)
    }

    private func loadOrderList(refresh: Bool, api: OrderAPI) async {
        let phone = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
        let isPhoneSearch = !phone.isEmpty && Self.isValidPhone(phone)

        let storeId = AppStore.shared.session.currentStoreId
        if storeId <= 0 {
            finishLoading()
            orderList = []
            canLoadMore = false
            onShowMessage?("店铺信息异常，请先选择店铺")
            return
        }

        let orderStatus: Int?
        let start: String?
        let end: String?
        let userPhone: String?

        if isPhoneSearch {
            orderStatus = 0
            start = nil
            end = nil
            userPhone = phone
        } else {
            orderStatus = Self.apiOrderStatus(forTabIndex: tabIndex)
            start = startTime.map { apiDateFormatter.string(from: $0) }
            end = endTime.map { apiDateFormatter.string(from: $0) }
            userPhone = nil
        }

        do {
            let response = try await api.storeOrderList(
                storeId: storeId,
                page: currentPage,
                userPhone: userPhone,
                orderStatus: orderStatus,
                startTime: start,
                endTime: end
            )
            totalCount = response.total
            if refresh || currentPage == 1 {
                orderList = response.list
                currentPage = 2
            } else {
                orderList.append(contentsOf: response.list)
                currentPage += 1
            }
            canLoadMore = orderList.count < totalCount
        } catch is CancellationError {
            return
        } catch {
            onShowMessage?(error.localizedDescription)
        }
        finishLoading()
    }

    private func executeStoreOrderVerify(_ request: StoreOrderVerifyRequest, api: OrderAPI) async {
        do {
            let response = try await api.storeOrderVerify(request)
            writeOffResponse = response
            if response.orderVerify {
                await refreshOrderList(api: api)
            }
            notifyStateChange()
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    private func finishLoading() {
        isRefreshing = false
        isLoadingMore = false
        notifyStateChange()
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}
