import Foundation
import UIKit
import CoreLocation
import BaiduMapAPI_Map
import BaiduMapAPI_Base

// Helper class for RichView item click handling
@objc class RichViewClickTarget: NSObject {
    weak var mapViewImpl: MapViewImpl?
    let overlayId: Int
    let itemIndex: Int

    init(mapViewImpl: MapViewImpl, overlayId: Int, itemIndex: Int) {
        self.mapViewImpl = mapViewImpl
        self.overlayId = overlayId
        self.itemIndex = itemIndex
    }

    @objc func handleClick() {
        NSLog("[RichView] item clicked: overlayId=%d, itemIndex=%d", overlayId, itemIndex)
        mapViewImpl?.onRichViewItemClicked(overlayId: overlayId, itemIndex: itemIndex)
    }
}

@objc public class MapViewImpl: UIView, BMKMapViewDelegate {

    @objc public let mapView: BMKMapView

    // 基础事件标志
    @objc public var isMapLoaded: Bool = false
    @objc public var renderReady: Bool = false
    @objc public var regionChangedStart: Bool = false
    @objc public var regionChanging: Bool = false
    @objc public var regionChangedFinish: Bool = false

    @objc public var mapTapped: Bool = false
    @objc public var poiTapped: Bool = false
    @objc public var longPressed: Bool = false
    @objc public var doublePressed: Bool = false

    // 区域事件数据
    @objc public var changeReason: UInt32 = 0
    @objc public var centerLatitude: Double = 0
    @objc public var centerLongitude: Double = 0
    @objc public var zoomLevelValue: Double = 12

    // 点击地图空白处
    @objc public var tappedLatitude: Double = 0
    @objc public var tappedLongitude: Double = 0

    // 点击 POI
    @objc public var tappedPoiName: String = ""
    @objc public var tappedPoiUid: String = ""
    @objc public var tappedPoiLatitude: Double = 0
    @objc public var tappedPoiLongitude: Double = 0

    // 长按
    @objc public var longPressedLatitude: Double = 0
    @objc public var longPressedLongitude: Double = 0

    // 双击
    @objc public var doublePressedLatitude: Double = 0
    @objc public var doublePressedLongitude: Double = 0

    // overlay tap (unified)
    @objc public var tappedOverlayId: Int = 0
    @objc public var tappedOverlayType: String = ""
    @objc public var tappedIsRichView: Bool = false
    @objc public var tappedRichViewItemIndex: Int = -1
    @objc public var overlayTapped: Bool = false
    @objc public var multiPointTapped: Bool = false
    @objc public var tappedMultiPointOverlayId: Int = 0
    @objc public var tappedMultiPointIndex: Int = -1
    @objc public var tappedMultiPointLat: Double = 0
    @objc public var tappedMultiPointLng: Double = 0
    @objc public var tappedMultiPointTitle: String = ""
    @objc public var coordTypeValue: String = "gcj02"
    @objc public var customMapStylePathValue: String = ""
    @objc public var mapStyleModeValue: String = "default"

    // 覆盖物缓存，extension 需要跨文件访问，保持 internal 级别。
    var markerOverlays: [Int: BMKIconMarker] = [:]
    var polylineOverlays: [Int: BMKPolyline] = [:]
    var polygonOverlays: [Int: BMKPolygon] = [:]
    var circleOverlays: [Int: BMKCircle] = [:]
    var labelOverlays: [Int: BMKTextMarker] = [:]
    var multiPointOverlays: [Int: BMKMultiPointOverlay] = [:]
    var richViewMarkerIds: Set<Int> = []

    // 统一全局自增 ID 计数器，避免跨类型 ID 碰撞
    var nextOverlayId: Int = 0

    // RichView target 必须强引用，避免 BMKBaseUIView 的 target 生命周期悬空。
    var richViewClickTargets: [Int: [Int: BMKBaseUIView]] = [:]
    var richViewInstances: [Int: BMKRichView] = [:]
    var richViewClickHandlers: [RichViewClickTarget] = []

    // zIndex存储
    var overlayZIndexes: [Int: Int] = [:]
    // visible存储
    var overlayVisibilities: [Int: Bool] = [:]

    @objc public override init(frame: CGRect) {
        self.mapView = BMKMapView(frame: frame)
        super.init(frame: frame)
        self.mapView.delegate = self
        self.addSubview(self.mapView)
    }

    @objc public convenience init() {
        self.init(frame: CGRect.zero)
    }

    @objc required public init?(coder: NSCoder) {
        return nil
    }

    @objc public override func layoutSubviews() {
        super.layoutSubviews()
        self.mapView.frame = self.bounds
    }

    @objc public func setMapType(_ mapType: String) {
        switch mapType {
        case "satellite":
            self.mapView.mapType = BMKMapType.satellite
        case "none":
            self.mapView.mapType = BMKMapType.none
        default:
            self.mapView.mapType = BMKMapType.standard
        }
    }

    @objc public func setMapStyleMode(_ mode: String) {
        self.mapStyleModeValue = mode
        self.mapView.setCustomMapStyleEnable(mode == "custom")
    }

    @objc public func setCustomMapStylePath(_ stylePath: String) {
        self.customMapStylePathValue = stylePath
        let bundlePath = self.resolveBundleStylePath(stylePath)
        self.mapView.setCustomMapStylePath(bundlePath)
        let applyResult = self.mapView.setCustomMapStyleEnable(self.mapStyleModeValue == "custom")
        NSLog("setCustomMapStylePath raw=\(stylePath) bundlePath=\(bundlePath) applyResult=\(applyResult)")
    }

    @objc public func setCustomMapStyleById(_ styleId: String, onSuccess: ((String?) -> Void)?, onFailure: ((String?, String?) -> Void)?) {
        if styleId.isEmpty {
            let applyResult = self.mapView.setCustomMapStyleEnable(false)
            NSLog("setCustomMapStyleById empty styleId, disable custom style applyResult=\(applyResult)")
            return
        }
        let option = BMKCustomMapStyleOption()
        option.customMapStyleID = styleId
        self.mapView.setCustomMapStyleWith(option, preLoad: { path in
            NSLog("setCustomMapStyleById preLoad: \(path ?? "")")
        }, success: { path in
            NSLog("setCustomMapStyleById success: \(path ?? "")")
			self.mapView.setCustomMapStyleEnable(true)
            onSuccess?(path)
        }) { error, path in
            NSLog("setCustomMapStyleById failure: \(String(describing: error)), path: \(path ?? "")")
            onFailure?(error.localizedDescription, path)
        }
    }

    private func resolveBundleStylePath(_ stylePath: String) -> String {
        let fileName = self.extractStyleFileName(stylePath)
        if fileName.isEmpty {
            return stylePath
        }
        if let bundlePath = Bundle.main.path(forResource: fileName, ofType: "sty") {
            return bundlePath
        }
        return stylePath
    }

    private func extractStyleFileName(_ stylePath: String) -> String {
        if stylePath.isEmpty {
            return ""
        }
        let nsPath = stylePath as NSString
        let fileName = nsPath.lastPathComponent as NSString
        return fileName.deletingPathExtension
    }

    @objc public func setCoordType(_ coordType: String) {
        self.coordTypeValue = coordType
        self.applyCoordType(coordType)
    }

    private func applyCoordType(_ coordType: String) {
        if coordType == "gcj02" {
            _ = BMKMapManager.setCoordinateTypeUsedInBaiduMapSDK(BMK_COORD_TYPE.COORDTYPE_COMMON)
        } else {
            _ = BMKMapManager.setCoordinateTypeUsedInBaiduMapSDK(BMK_COORD_TYPE.COORDTYPE_BD09LL)
        }
    }

    @objc public func setOverlayZIndex(_ overlayId: Int, _ zIndex: Int) {
        self.overlayZIndexes[overlayId] = zIndex
        self.reorderOverlaysByZIndex()
    }

    @objc public func setOverlayVisible(_ overlayId: Int, _ visible: Bool) {
        self.overlayVisibilities[overlayId] = visible
        // marker - 使用添加/移除方式控制可见性
        if let marker = self.markerOverlays[overlayId] {
            if visible {
                if self.mapView.annotations?.contains(where: { $0 as? BMKIconMarker === marker }) != true {
                    self.mapView.add(marker)
                }
            } else {
                self.mapView.remove(marker)
            }
        }
        // polyline
        if let polyline = self.polylineOverlays[overlayId] {
            if visible {
                if self.mapView.overlays?.contains(where: { $0 as? BMKPolyline == polyline }) != true {
                    self.mapView.add(polyline)
                }
            } else {
                self.mapView.remove(polyline)
            }
        }
        // polygon
        if let polygon = self.polygonOverlays[overlayId] {
            if visible {
                if self.mapView.overlays?.contains(where: { $0 as? BMKPolygon == polygon }) != true {
                    self.mapView.add(polygon)
                }
            } else {
                self.mapView.remove(polygon)
            }
        }
        // circle
        if let circle = self.circleOverlays[overlayId] {
            if visible {
                if self.mapView.overlays?.contains(where: { $0 as? BMKCircle == circle }) != true {
                    self.mapView.add(circle)
                }
            } else {
                self.mapView.remove(circle)
            }
        }
        // label - 使用添加/移除方式控制可见性
        if let label = self.labelOverlays[overlayId] {
            if visible {
                if self.mapView.annotations?.contains(where: { $0 as? BMKTextMarker === label }) != true {
                    self.mapView.add(label)
                }
            } else {
                self.mapView.remove(label)
            }
        }
        // multipoint
        if let multiPoint = self.multiPointOverlays[overlayId] {
            if visible {
                if self.mapView.overlays?.contains(where: { $0 as? BMKMultiPointOverlay == multiPoint }) != true {
                    self.mapView.add(multiPoint)
                }
            } else {
                self.mapView.remove(multiPoint)
            }
        }
    }

    private func reorderOverlaysByZIndex() {
        var allOverlays: [(id: Int, zIndex: Int, overlay: BMKOverlay)] = []

        for (id, marker) in self.markerOverlays {
            let z = self.overlayZIndexes[id] ?? 0
            allOverlays.append((id: id, zIndex: z, overlay: marker))
        }
        for (id, polyline) in self.polylineOverlays {
            let z = self.overlayZIndexes[id] ?? 0
            allOverlays.append((id: id, zIndex: z, overlay: polyline))
        }
        for (id, polygon) in self.polygonOverlays {
            let z = self.overlayZIndexes[id] ?? 0
            allOverlays.append((id: id, zIndex: z, overlay: polygon))
        }
        for (id, circle) in self.circleOverlays {
            let z = self.overlayZIndexes[id] ?? 0
            allOverlays.append((id: id, zIndex: z, overlay: circle))
        }
        for (id, label) in self.labelOverlays {
            let z = self.overlayZIndexes[id] ?? 0
            allOverlays.append((id: id, zIndex: z, overlay: label))
        }
        for (id, multiPoint) in self.multiPointOverlays {
            let z = self.overlayZIndexes[id] ?? 0
            allOverlays.append((id: id, zIndex: z, overlay: multiPoint))
        }

        allOverlays.sort { $0.zIndex < $1.zIndex }

        for (_, overlay) in allOverlays.enumerated() {
            self.mapView.remove(overlay.overlay)
        }
        for (_, overlay) in allOverlays.enumerated() {
            // 仅添加可见的覆盖物，隐藏的覆盖物不重新添加
            let isVisible = self.overlayVisibilities[overlay.id] ?? true
            if isVisible {
                self.mapView.add(overlay.overlay)
            }
        }
    }
}
