
import SwiftUI
import CoreLocation
import CoreMotion
import HealthKit
import BackgroundTasks
import WidgetKit
import Combine

class CompassManager: NSObject, ObservableObject, CLLocationManagerDelegate {
    
    @Published var angle: Double = 0.0
    @Published var heading: Double = 0.0
    @Published var longitude: Double = 0.0
    @Published var latitude: Double = 0.0
    @Published var altitude: Double = 0.0
    @Published var pressure: Double = 0.0
    @Published var dirction: String = ""
    @Published var step: Int = 0
    @Published var magneticHeading: Double = 0.0
    @Published var userLocation: CLLocationCoordinate2D?
    
    private let healthStore = HKHealthStore()
    
    private let altimeter = CMAltimeter()
    
    private var motionManager = CMMotionManager()
    
    private var locationManager = CLLocationManager()
    
    
    override init() {
        super.init()
        
        
        locationManager.delegate = self
        locationManager.headingFilter = 1
        start()
        locationManager.requestWhenInUseAuthorization()
        
    }
    
    public func loadaltimeterandhealth(){

        startAltimeterUpdates()
       requestHealthAuthorization()
    }
    
    // 开始处理后台位置更新任务
    public  func handleLocationUpdateTask(task: BGAppRefreshTask) {
        print("处理后台位置更新任务")
        
        Task {
            // 异步加载数据或执行长时间运行的任务
            await scheduleBackgroundLocationUpdate()  // 调度下一次位置更新任务
            // 启动位置更新
            locationManager.delegate = self
            locationManager.requestWhenInUseAuthorization()

            locationManager.startUpdatingLocation()
            task.expirationHandler = {
                DispatchQueue.main.async {
                    self.locationManager.stopUpdatingLocation() // Ensure UI updates on the main thread
                    task.setTaskCompleted(success: false)
                    print("后台任务超时，停止位置更新")
                }
            }
        }
        
    }
    
    
    func scheduleBackgroundLocationUpdate() async{
        let request = BGAppRefreshTaskRequest(identifier: "com.toolboxes.locationUpdate")
        // 设置后台任务的最早执行时间（例如1小时后）
        request.earliestBeginDate = Date(timeIntervalSinceNow: 60 * 60 * 60) // 每小时调度一次
        
        do {
            try BGTaskScheduler.shared.submit(request)
            print("成功调度后台位置更新任务")
        } catch {
            print("无法调度后台任务: \(error)")
        }
    }
    
    func requestPermission() {
        locationManager.requestWhenInUseAuthorization()
    }
    
    func requestLocation() {
        locationManager.requestLocation()
    }
    
    func start(){
        
        locationManager.delegate = self
#if targetEnvironment(simulator)
        print("模拟器不支持指南针功能")
#else
        do {
            
            try     locationManager.startUpdatingHeading()
            locationManager.startUpdatingLocation()
        } catch {
            print("无法启动指南针功能: \(error)")
        }
#endif
        
      
    }
    
    func stop() {
        locationManager.stopUpdatingLocation()
        locationManager.stopUpdatingHeading()
    }
    
    
    func locationManager(_ manager: CLLocationManager, didUpdateHeading newHeading: CLHeading) {
        DispatchQueue.main.async { [weak self] in
            guard let self = self else { return }
            //
            //            let heading = newHeading.trueHeading > 0 ? newHeading.trueHeading : newHeading.magneticHeading
            //
            //            self.heading = heading
            //            withAnimation(Animation.linear(duration: 0.5)) {
            self.heading = newHeading.trueHeading.normalized
            //            }
            
            
            self.magneticHeading = newHeading.magneticHeading
            self.dirction = direction(for: heading)
            
        }
    }
    
    func  locationManager(_ manager:  CLLocationManager , didUpdateLocations locations: [ CLLocation ]) {
        DispatchQueue.main.async { [self] in
            
            let  currLocation: CLLocation  = locations.last!
            self.longitude = currLocation.coordinate.longitude
            self.altitude = currLocation.altitude
            self.latitude = currLocation.coordinate.latitude
            guard let location = locations.first else { return }
            userLocation = location.coordinate
            
            // 保存位置数据到 UserDefaults（用于小组件）
            appGroupDefaults?.set(currLocation.coordinate.latitude, forKey: "latitude")
            appGroupDefaults?.set(currLocation.coordinate.longitude, forKey: "longitude")
            appGroupDefaults?.set(currLocation.altitude, forKey: "altitude")
            
            // 通知小组件刷新
            WidgetCenter.shared.reloadAllTimelines()
        }
    }
    
    func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
        // 可以在这里处理权限变更
    }
    
    func locationManager(_ manager: CLLocationManager, didFailWithError error: Error) {
        print("Failed to find user's location: \(error.localizedDescription)")
    }
    
    func startAltimeterUpdates() {
        if CMAltimeter.isRelativeAltitudeAvailable() {
            altimeter.startRelativeAltitudeUpdates(to: OperationQueue.main) { data, error in
                if let altimeterData = data {
                    self.pressure = altimeterData.pressure.doubleValue * 10
                } else {
                    print("无法获取气压/海拔数据: \(String(describing: error))")
                }
            }
        } else {
            print("该设备不支持气压传感器")
        }
    }
    
    func direction(for heading: Double) -> String {
        switch heading {
        case 0..<22.5, 337.5..<360:
            return L("N")
        case 22.5..<67.5:
            return L("NE")
        case 67.5..<112.5:
            return L("E")
        case 112.5..<157.5:
            return L("SE")
        case 157.5..<202.5:
            return L("S")
            
        case 202.5..<247.5:
            return L("SW")
            
        case 247.5..<292.5:
            return L("W")
            
        case 292.5..<337.5:
            return L("NW")
        default:
            return ""
        }
    }
    
    
    
    func requestHealthAuthorization() {
        guard let stepCountType = HKObjectType.quantityType(forIdentifier: .stepCount) else { return }
        let typesToShare: Set = [stepCountType]
        let typesToRead: Set = [stepCountType]
        
        healthStore.requestAuthorization(toShare: typesToShare, read: typesToRead) { success, error in
            DispatchQueue.main.async {
                if success {
                    self.fetchStepCount()
                } else {
                    // 如果请求权限失败，使用默认值
                    self.step = 0
                }
            }
        }
    }
    
    private func fetchStepCount() {
        let stepCountType = HKObjectType.quantityType(forIdentifier: .stepCount)!
        let calendar = Calendar.current
        let startDate = calendar.startOfDay(for: Date())
        let endDate = Date()
        
        let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: .strictEndDate)
        let query = HKSampleQuery(sampleType: stepCountType, predicate: predicate, limit: HKObjectQueryNoLimit, sortDescriptors: nil) { (query, results, error) in
            DispatchQueue.main.async {
                guard let samples = results as? [HKQuantitySample] else {
                    self.step = 0
                    return
                }
                let totalSteps = samples.reduce(0) { $0 + $1.quantity.doubleValue(for: HKUnit.count()) }
                print("Total steps: \(totalSteps)")
                self.step = Int(totalSteps)
            }
        }
        healthStore.execute(query)
    }
}


extension Double {
    var normalized: Double {
        let normalizedValue = self.truncatingRemainder(dividingBy: 360.0)
        return normalizedValue < 0 ? normalizedValue + 360.0 : normalizedValue
    }
}
