//
//  LocationManager.swift
//  Pods
//
//  Created by Groot on 2025/5/15.
//

import Foundation
import CoreLocation
import Flutter

class LocationManager: NSObject {

    static let shared = LocationManager()

    private var locationUpdateEventChannel: FlutterEventChannel?
    private var locationEventSink: FlutterEventSink?

    private let locationManager = CLLocationManager()

    #if DEBUG
    private let filterDistance: CLLocationDistance = 5
    #else
    private let filterDistance: CLLocationDistance = 20
    #endif
    private var lastLocation: CLLocation?
    private var lastUpdateTime: Date?

    var onLocationUpdate: ((CLLocation) -> Void)?

    private override init() {
        super.init()
        locationManager.delegate = self
        setup()
    }
    
    func initChannel(withMessenger messenger: FlutterBinaryMessenger) {
        locationUpdateEventChannel = FlutterEventChannel(name: MapKitConstans.locationUpdateEventChannelName, binaryMessenger: messenger)
        locationUpdateEventChannel?.setStreamHandler(self)
    }

    func start(withMessenger messenger: FlutterBinaryMessenger) -> Bool {
        // permission detect
        switch CLLocationManager.authorizationStatus() {
        case .authorizedWhenInUse, .authorizedAlways:
            locationManager.startUpdatingLocation()
            //setupMessenger(messenger: messenger)
            return true
        case .notDetermined:
            return false
        default:
            print("LocationManager: authorizationStatus: \(CLLocationManager.authorizationStatus())")
            return false
        }
    }

    func stop() {
        locationManager.stopUpdatingLocation()
    }

//    func setupMessenger(messenger: FlutterBinaryMessenger) {
//        guard locationUpdateEventChannel == nil && locationEventSink == nil else { return }
//        locationUpdateEventChannel = FlutterEventChannel(name: MapKitConstans.locationUpdateEventChannelName, binaryMessenger: messenger)
//        locationUpdateEventChannel?.setStreamHandler(self)
//    }

    func setup() {
        locationManager.allowsBackgroundLocationUpdates = true
        locationManager.pausesLocationUpdatesAutomatically = false
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
//        locationManager.distanceFilter = filterDistance
        locationManager.activityType = .automotiveNavigation
        locationManager.showsBackgroundLocationIndicator = false
    }

    static func getAddress(location: CLLocation) async -> String? {   
        let geocoder = CLGeocoder()
        return await withCheckedContinuation { continuation in
            geocoder.reverseGeocodeLocation(location) { (placemarks, error) in
                if let error = error {
                    print("反向地理编码失败: \(error.localizedDescription)")
                    continuation.resume(returning: nil)
                    return
                }
                
                if let placemark = placemarks?.first {
                    // 获取完整地址
                    let address = [
                        placemark.country,
                        placemark.administrativeArea,
                        placemark.locality,
                        placemark.subLocality,
                        placemark.thoroughfare,
                        placemark.subThoroughfare,
                        placemark.name
                    ].compactMap { $0 }.joined(separator: "")
                    
                    continuation.resume(returning: address)
                } else {
                    continuation.resume(returning: nil)
                }
            }
        }
    }
}

extension LocationManager: CLLocationManagerDelegate {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
        guard let location = locations.last, isLocationCanUpdate(location: location) else { return }
        onLocationUpdate?(location)
        if let eventSink = locationEventSink {
            Task {
                // 转换GPS坐标系到中国坐标系
                let transformedCoordinate = location.coordinate.wgc84ToGCJ02
                let atLocation = ATMapLocation.fromLocation(location: location)
                atLocation.longitude = transformedCoordinate.longitude
                atLocation.latitude = transformedCoordinate.latitude
                // 获取地址
                atLocation.address = await LocationManager.getAddress(location: location)
                
                let jsonMessage = atLocation.toJson()
                print(jsonMessage)
                await MainActor.run {
                    eventSink(jsonMessage)
                }
            }
            
        }
    }

    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("LocationManager: didFailWithError: \(error)")
    }

    func isLocationCanUpdate(location: CLLocation) -> Bool {
        if let lastLocation = lastLocation {
            let distance = location.distance(from: lastLocation)
            let timeInterval = location.timestamp.timeIntervalSince(lastUpdateTime ?? Date())
            if timeInterval < 5.0 {
                return false
            }
        }
        lastLocation = location
        lastUpdateTime = location.timestamp
        return true
    }
}

extension LocationManager: FlutterStreamHandler {
    func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        locationEventSink = events
        return nil
    }

    func onCancel(withArguments arguments: Any?) -> FlutterError? {
        locationEventSink = nil
        return nil
    }
}
