//
//  LocationReportViewModel.swift
//  suixinkan
//

import Foundation

/// 独立位置上报页 ViewModel，对齐 Android `LocationReportViewModel` + 共享上报逻辑。
final class LocationReportViewModel {

    private(set) var currentLatitude: Double?
    private(set) var currentLongitude: Double?
    private(set) var currentAddress: String?
    private(set) var isLocating = false
    private(set) var isMarking = false
    private(set) var markerLatitude: Double?
    private(set) var markerLongitude: Double?
    private(set) var markerAddress: String?
    private(set) var showOnlineStatusDialog = false
    private(set) var showLocationReportSuccessDialog = false
    private(set) var reportTimeText = ""

    let locationStateStore: HomeLocationStateStore
    let locationReportService: LocationReportService

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

    private let locationProvider: any LocationProviding

    init(
        locationStateStore: HomeLocationStateStore = .shared,
        locationProvider: any LocationProviding = LocationProvider.shared
    ) {
        self.locationStateStore = locationStateStore
        self.locationProvider = locationProvider
        self.locationReportService = LocationReportService(
            locationStateStore: locationStateStore,
            locationProvider: locationProvider
        )
        self.locationStateStore.observe(self) { [weak self] in
            self?.notifyStateChange()
        }
    }

    deinit {
        locationStateStore.removeObserver(self)
    }

    var isOnline: Bool { locationStateStore.isOnline }
    var countdownDisplayText: String { locationStateStore.countdownDisplayTextSingleHour }
    var reminderMinutes: Int { locationStateStore.reminderMinutes }
    var isReporting: Bool { locationReportService.isReporting }

    /// 进入页面时恢复在线倒计时。
    func restoreStateIfNeeded() {
        locationStateStore.restoreStateIfNeeded()
        notifyStateChange()
    }

    /// 开始定位并更新地图中心。
    func startLocation() {
        guard !isLocating else { return }
        isLocating = true
        notifyStateChange()
        Task {
            defer {
                isLocating = false
                notifyStateChange()
            }
            do {
                let snapshot = try await locationProvider.requestSnapshot()
                currentLatitude = snapshot.latitude
                currentLongitude = snapshot.longitude
                currentAddress = snapshot.address.isEmpty
                    ? String(format: "%.5f, %.5f", snapshot.latitude, snapshot.longitude)
                    : snapshot.address
                notifyStateChange()
            } catch {
                onShowMessage?((error as? LocalizedError)?.errorDescription ?? error.localizedDescription)
            }
        }
    }

    func toggleMarking() {
        isMarking.toggle()
        if !isMarking {
            markerLatitude = nil
            markerLongitude = nil
            markerAddress = nil
        }
        notifyStateChange()
    }

    /// 地图点击设置标记点并逆地理。
    func setMarkerLocation(latitude: Double, longitude: Double) {
        guard isMarking else { return }
        markerLatitude = latitude
        markerLongitude = longitude
        markerAddress = nil
        notifyStateChange()
        Task {
            let address = await locationProvider.reverseGeocode(latitude: latitude, longitude: longitude)
            markerAddress = address.isEmpty
                ? String(format: "%.5f, %.5f", latitude, longitude)
                : address
            notifyStateChange()
        }
    }

    func showOnlineStatusSwitchDialog() {
        showOnlineStatusDialog = true
        notifyStateChange()
    }

    func hideOnlineStatusSwitchDialog() {
        showOnlineStatusDialog = false
        notifyStateChange()
    }

    func hideLocationReportSuccessDialog() {
        showLocationReportSuccessDialog = false
        notifyStateChange()
    }

    func updateReminderMinutes(_ minutes: Int) {
        locationStateStore.updateReminderMinutes(minutes)
        notifyStateChange()
    }

    func switchOnlineStatus(api: HomeAPI) async {
        hideOnlineStatusSwitchDialog()
        do {
            let goingOnline = !isOnline
            if let result = try await locationReportService.switchOnlineStatus(api: api) {
                applyReportSuccess(result)
                onShowMessage?(goingOnline ? "已切换到在线状态，正在上报位置" : "已切换到离线状态")
            } else {
                onShowMessage?("已切换到离线状态")
            }
        } catch let error as LocationReportServiceError {
            onShowMessage?(error.localizedDescription)
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    /// 立即上报：标记模式 type=2，否则 type=1。
    func reportLocation(api: HomeAPI) async {
        if isMarking {
            guard let lat = markerLatitude, let lng = markerLongitude else {
                onShowMessage?("请先在地图上选择标记点")
                return
            }
            await reportCoordinates(api: api, latitude: lat, longitude: lng, address: markerAddress, type: 2)
            return
        }

        guard let lat = currentLatitude, let lng = currentLongitude else {
            onShowMessage?("正在定位中，请稍候")
            return
        }
        await reportCoordinates(api: api, latitude: lat, longitude: lng, address: currentAddress, type: 1)
    }

    private func reportCoordinates(
        api: HomeAPI,
        latitude: Double,
        longitude: Double,
        address: String?,
        type: Int
    ) async {
        do {
            let result = try await locationReportService.reportWithCoordinates(
                api: api,
                latitude: latitude,
                longitude: longitude,
                address: address,
                type: type
            )
            applyReportSuccess(result)
            onShowMessage?("位置上报成功")
        } catch let error as LocationReportServiceError {
            onShowMessage?(error.localizedDescription)
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    private func applyReportSuccess(_ result: LocationReportSuccessResult) {
        if result.shouldShowSuccessDialog {
            reportTimeText = result.reportTimeText
            showLocationReportSuccessDialog = true
        }
        notifyStateChange()
    }

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