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

import CoreLocation
import Foundation
import Combine

/// 前台定位结果实体，表示一次即时定位得到的坐标和可展示地址。
struct ForegroundLocationResult: Equatable {
    let latitude: Double
    let longitude: Double
    let address: String
}

/// 前台定位 Provider，只负责当前页面主动请求位置，不缓存、不后台持续定位。
@MainActor
final class ForegroundLocationProvider: NSObject, ObservableObject {
    private let manager = CLLocationManager()
    private let geocoder = CLGeocoder()
    @Published private var continuation: CheckedContinuation<ForegroundLocationResult, Error>?

    override init() {
        super.init()
        manager.delegate = self
        manager.desiredAccuracy = kCLLocationAccuracyBest
    }

    /// 请求一次当前位置，成功后尝试反解析为地址。
    func requestCurrentLocation() async throws -> ForegroundLocationResult {
        if let continuation {
            continuation.resume(throwing: LocationProviderError.duplicatedRequest)
            self.continuation = nil
        }
        let status = manager.authorizationStatus
        if status == .notDetermined {
            manager.requestWhenInUseAuthorization()
        }

        return try await withCheckedThrowingContinuation { continuation in
            self.continuation = continuation
            manager.requestLocation()
        }
    }

    /// 将 CLLocation 转为页面可展示的定位结果。
    private func makeResult(from location: CLLocation) async -> ForegroundLocationResult {
        let address: String
        if let placemark = try? await geocoder.reverseGeocodeLocation(location).first {
            address = [
                placemark.administrativeArea,
                placemark.locality,
                placemark.subLocality,
                placemark.thoroughfare,
                placemark.name
            ]
            .compactMap { $0 }
            .filter { !$0.isEmpty }
            .joined(separator: "")
        } else {
            address = "当前位置"
        }
        return ForegroundLocationResult(
            latitude: location.coordinate.latitude,
            longitude: location.coordinate.longitude,
            address: address.isEmpty ? "当前位置" : address
        )
    }
}

extension ForegroundLocationProvider: CLLocationManagerDelegate {
    /// 定位成功回调，返回最近一次坐标。
    nonisolated func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last else { return }
        Task { @MainActor in
            guard let continuation = self.continuation else { return }
            self.continuation = nil
            let result = await self.makeResult(from: location)
            continuation.resume(returning: result)
        }
    }

    /// 定位失败回调，将错误传给当前请求方。
    nonisolated func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        Task { @MainActor in
            guard let continuation = self.continuation else { return }
            self.continuation = nil
            continuation.resume(throwing: error)
        }
    }
}

/// 前台定位 Provider 错误实体。
enum LocationProviderError: LocalizedError {
    case duplicatedRequest

    var errorDescription: String? {
        switch self {
        case .duplicatedRequest:
            "已有定位请求正在执行"
        }
    }
}
