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

import Foundation
import Combine

/// 位置上报 ViewModel，负责页面内在线状态、坐标、倒计时和提交动作。
@MainActor
final class LocationReportViewModel: ObservableObject {
    @Published var isOnline = false
    @Published var reminderMinutes = 30
    @Published var secondsUntilReport = 0
    @Published var currentCoordinate: LocationCoordinate?
    @Published var markedCoordinate: LocationCoordinate?
    @Published var currentAddress = ""
    @Published var markedAddress = ""
    @Published var lastReportText = ""
    @Published var errorMessage: String?
    @Published var isSubmitting = false

    /// 倒计时展示文案。
    var countdownText: String {
        guard secondsUntilReport > 0 else { return "可立即上报" }
        let hours = secondsUntilReport / 3600
        let minutes = (secondsUntilReport % 3600) / 60
        return "\(hours)小时\(minutes)分钟后可再次提醒"
    }

    /// 设置当前位置。
    func applyCurrentLocation(latitude: Double, longitude: Double, address: String) {
        currentCoordinate = LocationCoordinate(latitude: latitude, longitude: longitude)
        currentAddress = address
    }

    /// 设置标记点位置。
    func applyMarkedLocation(latitude: Double, longitude: Double, address: String) {
        markedCoordinate = LocationCoordinate(latitude: latitude, longitude: longitude)
        markedAddress = address
    }

    /// 切换在线状态；切到在线时会提交一次状态上报。
    func setOnline(
        _ value: Bool,
        staffId: Int?,
        scenicId: Int?,
        api: any LocationReportServing
    ) async -> Bool {
        isOnline = value
        guard value else { return true }
        return await submit(type: .onlineStatus, staffId: staffId, scenicId: scenicId, api: api)
    }

    /// 提交指定类型的位置上报。
    func submit(
        type: LocationReportType,
        staffId: Int?,
        scenicId: Int?,
        api: any LocationReportServing
    ) async -> Bool {
        guard !isSubmitting else { return false }
        guard let staffId, staffId > 0 else {
            errorMessage = "缺少上报人员"
            return false
        }
        guard let scenicId, scenicId > 0 else {
            errorMessage = "缺少当前景区"
            return false
        }

        let source = reportSource(for: type)
        guard let coordinate = source.coordinate else {
            errorMessage = "请先获取或选择位置"
            return false
        }
        let address = source.address.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !address.isEmpty else {
            errorMessage = "请填写位置地址"
            return false
        }

        isSubmitting = true
        errorMessage = nil
        defer { isSubmitting = false }

        do {
            let response = try await api.reportLocation(
                staffId: staffId,
                latitude: coordinate.latitude,
                longitude: coordinate.longitude,
                address: address,
                type: type,
                scenicId: scenicId
            )
            secondsUntilReport = response.expired > 0 ? response.expired : 7200
            lastReportText = LocationReportViewModel.displayFormatter.string(from: Date())
            return true
        } catch {
            errorMessage = error.localizedDescription
            return false
        }
    }

    /// 页面内倒计时每秒递减。
    func tick() {
        guard secondsUntilReport > 0 else { return }
        secondsUntilReport -= 1
    }

    /// 根据上报类型选择当前坐标或标记点坐标。
    private func reportSource(for type: LocationReportType) -> (coordinate: LocationCoordinate?, address: String) {
        switch type {
        case .marked:
            (markedCoordinate ?? currentCoordinate, markedAddress.isEmpty ? currentAddress : markedAddress)
        case .all, .immediate, .onlineStatus:
            (currentCoordinate, currentAddress)
        }
    }

    private static let displayFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
        return formatter
    }()
}

/// 位置上报历史 ViewModel，负责筛选、日期和分页加载。
@MainActor
final class LocationReportHistoryViewModel: ObservableObject {
    @Published var selectedType: LocationReportType = .all
    @Published var startDate: Date?
    @Published var endDate: Date?
    @Published var items: [LocationReportHistoryItem] = []
    @Published var errorMessage: String?
    private var isLoading = false
    @Published var isLoadingMore = false
    @Published var total = 0

    @Published private var page = 1
    private let pageSize = 20

    /// 是否还有下一页历史记录。
    var hasMore: Bool {
        items.count < total
    }

    /// 重新加载历史记录。
    func reload(staffId: Int?, api: any LocationReportServing) async {
        guard let staffId, staffId > 0 else {
            reset()
            errorMessage = "缺少上报人员"
            return
        }
        page = 1
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }

        do {
            let payload = try await api.locationReportList(
                staffId: staffId,
                page: page,
                pageSize: pageSize,
                type: selectedType,
                startDate: dateString(startDate),
                endDate: dateString(endDate)
            )
            items = payload.list
            total = payload.total
        } catch {
            items = []
            total = 0
            errorMessage = error.localizedDescription
        }
    }

    /// 加载下一页历史记录。
    func loadMore(staffId: Int?, api: any LocationReportServing) async {
        guard let staffId, staffId > 0, hasMore, !isLoading, !isLoadingMore else { return }
        isLoadingMore = true
        let nextPage = page + 1
        defer { isLoadingMore = false }

        do {
            let payload = try await api.locationReportList(
                staffId: staffId,
                page: nextPage,
                pageSize: pageSize,
                type: selectedType,
                startDate: dateString(startDate),
                endDate: dateString(endDate)
            )
            page = nextPage
            items.append(contentsOf: payload.list)
            total = payload.total
        } catch {
            errorMessage = error.localizedDescription
        }
    }

    /// 切换历史类型筛选并刷新。
    func selectType(_ type: LocationReportType, staffId: Int?, api: any LocationReportServing) async {
        guard selectedType != type else { return }
        selectedType = type
        await reload(staffId: staffId, api: api)
    }

    /// 清空历史状态。
    func reset() {
        items = []
        total = 0
        page = 1
        isLoading = false
        isLoadingMore = false
    }

    /// 将日期转为接口需要的 yyyy-MM-dd 字符串。
    private func dateString(_ date: Date?) -> String? {
        guard let date else { return nil }
        return Self.dateFormatter.string(from: date)
    }

    private static let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()
}
