//
//  MainTabScanHandler.swift
//  suixinkan
//

import CoreLocation
import UIKit

/// 主 Tab 中间扫码按钮结果处理，对齐 Android `MainTabViewModel.signIn`。
@MainActor
final class MainTabScanHandler {

    var onShowMessage: ((String) -> Void)?
    var onShowSignIn: ((OrderSignInResponse) -> Void)?
    var onShowWriteOff: ((WriteOffOrderResponse) -> Void)?
    var onMultiVerifyPending: ((MultiVerifyParseData) -> Void)?
    var onShowMultiVerifySheet: (([MultiTravelScenicSpotEntity], MultiTravelScenicSpotEntity?) -> Void)?
    var onNavigateBindAcquirer: ((Int) -> Void)?

    private let api: OrderAPI
    private let locationProvider: any LocationProviding
    private(set) var pendingMultiVerify: MultiVerifyParseData?

    init(api: OrderAPI, locationProvider: any LocationProviding = LocationProvider.shared) {
        self.api = api
        self.locationProvider = locationProvider
    }

    func handleScanResult(_ scanResult: String) async {
        guard !scanResult.isEmpty else {
            onShowMessage?("请扫描正确的二维码")
            return
        }

        guard let parsed = QRCodeScanResult.parse(scanResult) else {
            onShowMessage?("请扫描正确的二维码")
            return
        }

        switch parsed.method {
        case "check_in":
            await performCheckIn(scanResult: scanResult)
        case "order_verify":
            if AppStore.shared.session.currentAppRole == .storeAdmin {
                await performStoreVerify(parsed: parsed)
            } else {
                await performPhotographerVerify(jsonBody: parsed.rawJSON)
            }
        case "multi_verify":
            guard !parsed.orderNumber.isEmpty, parsed.userId > 0, parsed.timeLong > 0, !parsed.checkSum.isEmpty else {
                onShowMessage?("请扫描正确的多点位核销码")
                return
            }
            let pending = MultiVerifyParseData(
                orderNumber: parsed.orderNumber,
                userId: parsed.userId,
                time: parsed.timeLong,
                checkSum: parsed.checkSum
            )
            pendingMultiVerify = pending
            onMultiVerifyPending?(pending)
            await fetchSpotsForMultiVerify(pending: pending)
        case SaleUserQrParser.methodSaleUserBind:
            if let id = SaleUserQrParser.parseSaleUserId(scanResult), id > 0 {
                onNavigateBindAcquirer?(id)
            } else {
                onShowMessage?("请扫描正确的获客员二维码")
            }
        default:
            onShowMessage?("未知二维码，请检查后重试")
        }
    }

    func confirmMultiVerify(pending: MultiVerifyParseData, spot: MultiTravelScenicSpotEntity) async {
        do {
            let response = try await api.multiTravelOrderVerify(
                MultiTravelOrderVerifyRequest(
                    orderNumber: pending.orderNumber,
                    userId: pending.userId,
                    time: pending.time,
                    checkSum: pending.checkSum,
                    scenicSpotId: spot.scenicSpotId
                )
            )
            onShowSignIn?(response)
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    private func performCheckIn(scanResult: String) async {
        guard var json = parseJSONObject(scanResult) else {
            onShowMessage?("请扫描正确的二维码")
            return
        }
        json["scenic_id"] = String(AppStore.shared.session.currentScenicId)
        guard let body = serializeJSON(json) else { return }
        do {
            let response = try await api.orderCheckIn(jsonBody: body)
            onShowSignIn?(response)
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    private func performPhotographerVerify(jsonBody: String) async {
        do {
            let response = try await api.orderVerify(jsonBody: jsonBody)
            onShowWriteOff?(response)
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    private func performStoreVerify(parsed: QRCodeScanResult) async {
        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
        }
        do {
            let response = try await api.storeOrderVerify(
                StoreOrderVerifyRequest(
                    userId: parsed.userId,
                    orderNumber: parsed.orderNumber,
                    time: parsed.time,
                    storeId: storeId
                )
            )
            onShowWriteOff?(response)
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    private func fetchSpotsForMultiVerify(pending: MultiVerifyParseData) async {
        do {
            let coordinate = try await locationProvider.requestCoordinate()
            let response = try await api.multiTravelScenicSpotList(
                orderNumber: pending.orderNumber,
                lat: coordinate.latitude,
                lng: coordinate.longitude
            )
            let spots = response.entityList
            if spots.isEmpty {
                onShowMessage?("暂无可核销的打卡点")
            } else {
                onShowMultiVerifySheet?(spots, spots.first)
            }
        } catch LocationProviderError.permissionDenied {
            onShowMessage?(OrderLocationError.permissionDenied.errorDescription ?? "缺少定位权限，功能无法进行")
        } catch {
            onShowMessage?((error as? LocalizedError)?.errorDescription ?? error.localizedDescription)
        }
    }
}

private extension MainTabScanHandler {
    func parseJSONObject(_ text: String) -> [String: Any]? {
        guard let data = text.data(using: .utf8) else { return nil }
        return try? JSONSerialization.jsonObject(with: data) as? [String: Any]
    }

    func serializeJSON(_ json: [String: Any]) -> String? {
        guard let data = try? JSONSerialization.data(withJSONObject: json) else { return nil }
        return String(data: data, encoding: .utf8)
    }
}
