//
//  LocationReportViews.swift
//  suixinkan
//

import CoreLocation
import SnapKit
import UIKit

#if targetEnvironment(simulator)
import MapKit
#endif

/// 地图缩放/定位控件。
final class LocationReportMapControlStack: UIView {

    var onZoomIn: (() -> Void)?
    var onZoomOut: (() -> Void)?
    var onRelocate: (() -> Void)?
    private weak var relocateButton: UIButton?

    override init(frame: CGRect) {
        super.init(frame: frame)
        let zoomIn = makeButton(symbol: "plus", action: #selector(zoomInTapped))
        let zoomOut = makeButton(symbol: "minus", action: #selector(zoomOutTapped))
        let relocate = makeButton(symbol: "location.fill", action: #selector(relocateTapped))
        relocateButton = relocate

        let zoomStack = UIStackView(arrangedSubviews: [zoomIn, zoomOut])
        zoomStack.axis = .vertical
        zoomStack.spacing = 0
        zoomStack.backgroundColor = .white
        zoomStack.layer.cornerRadius = 12
        zoomStack.clipsToBounds = true

        relocate.backgroundColor = .white
        relocate.layer.cornerRadius = 12

        let stack = UIStackView(arrangedSubviews: [zoomStack, relocate])
        stack.axis = .vertical
        stack.spacing = 12
        addSubview(stack)
        stack.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
        [zoomIn, zoomOut, relocate].forEach { button in
            button.snp.makeConstraints { make in
                make.size.equalTo(44)
            }
        }
    }

    /// 更新定位按钮是否可用。
    func setRelocateEnabled(_ isEnabled: Bool) {
        relocateButton?.isEnabled = isEnabled
        relocateButton?.alpha = isEnabled ? 1 : 0.46
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    private func makeButton(symbol: String, action: Selector) -> UIButton {
        let button = UIButton(type: .system)
        button.setImage(UIImage(systemName: symbol), for: .normal)
        button.tintColor = AppColor.primary
        button.addTarget(self, action: action, for: .touchUpInside)
        return button
    }

    @objc private func zoomInTapped() { onZoomIn?() }
    @objc private func zoomOutTapped() { onZoomOut?() }
    @objc private func relocateTapped() { onRelocate?() }
}

/// 状态信息卡片。
final class LocationReportStatusCardView: UIView {

    var onOnlineStatusTap: (() -> Void)?
    var onReminderTap: (() -> Void)?

    private let onlineBadge = UILabel()
    private let countdownLabel = UILabel()
    private let reminderLabel = UILabel()

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        layer.cornerRadius = 10

        let statusTitle = makeTitle("当前状态")
        onlineBadge.font = .systemFont(ofSize: 12, weight: .medium)
        onlineBadge.textAlignment = .center
        onlineBadge.layer.cornerRadius = 4
        onlineBadge.clipsToBounds = true
        onlineBadge.isUserInteractionEnabled = true
        onlineBadge.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(onlineTapped)))

        let countdownTitle = makeTitle("距离下次上报时间")
        countdownLabel.font = .systemFont(ofSize: 16, weight: .medium)
        countdownLabel.textColor = AppColor.primary

        let reminderTitle = makeTitle("提醒设置")
        reminderLabel.font = .systemFont(ofSize: 16, weight: .medium)
        reminderLabel.textColor = AppColor.primary
        reminderLabel.isUserInteractionEnabled = true
        reminderLabel.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(reminderTapped)))

        let stack = UIStackView()
        stack.axis = .vertical
        stack.spacing = 12
        stack.addArrangedSubview(makeRow(left: statusTitle, right: onlineBadge))
        stack.addArrangedSubview(makeRow(left: countdownTitle, right: countdownLabel))
        stack.addArrangedSubview(makeRow(left: reminderTitle, right: reminderLabel))
        addSubview(stack)
        stack.snp.makeConstraints { make in
            make.edges.equalToSuperview().inset(15)
        }
        onlineBadge.snp.makeConstraints { make in
            make.width.greaterThanOrEqualTo(52)
            make.height.equalTo(28)
        }
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func apply(isOnline: Bool, countdown: String, reminderMinutes: Int) {
        onlineBadge.text = isOnline ? "在线" : "离线"
        onlineBadge.textColor = isOnline ? AppColor.online : UIColor(hex: 0x7B8EAA)
        onlineBadge.backgroundColor = isOnline ? UIColor(hex: 0xF0FDF4) : AppColor.inputBackground
        countdownLabel.text = countdown
        reminderLabel.text = reminderMinutes == 0 ? "不提醒" : "提前\(reminderMinutes)分钟"
    }

    @objc private func onlineTapped() { onOnlineStatusTap?() }
    @objc private func reminderTapped() { onReminderTap?() }

    private func makeTitle(_ text: String) -> UILabel {
        let label = UILabel()
        label.text = text
        label.font = .systemFont(ofSize: 14)
        label.textColor = AppColor.textPrimary
        return label
    }

    private func makeRow(left: UIView, right: UIView) -> UIView {
        let row = UIStackView(arrangedSubviews: [left, right])
        row.axis = .horizontal
        row.distribution = .equalSpacing
        row.alignment = .center
        return row
    }
}

/// 立即上报卡片。
final class LocationReportActionCardView: UIView {

    var onReportTap: (() -> Void)?

    private let reportButton = UIButton(type: .system)

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        layer.cornerRadius = 10

        let icon = UIImageView(image: UIImage(systemName: "arrow.up"))
        icon.tintColor = AppColor.primary
        let title = UILabel()
        title.text = "立即上报"
        title.font = .systemFont(ofSize: 16, weight: .bold)
        title.textColor = AppColor.textPrimary
        let subtitle = UILabel()
        subtitle.text = "您已进入打卡范围"
        subtitle.font = .systemFont(ofSize: 12)
        subtitle.textColor = AppColor.textTertiary

        let textStack = UIStackView(arrangedSubviews: [title, subtitle])
        textStack.axis = .vertical
        textStack.spacing = 4

        reportButton.backgroundColor = AppColor.primary
        reportButton.tintColor = .white
        reportButton.setImage(UIImage(systemName: "location.fill"), for: .normal)
        reportButton.layer.cornerRadius = 36
        reportButton.addTarget(self, action: #selector(reportTapped), for: .touchUpInside)

        addSubview(icon)
        addSubview(textStack)
        addSubview(reportButton)

        icon.snp.makeConstraints { make in
            make.leading.equalToSuperview().offset(15)
            make.centerY.equalToSuperview()
            make.size.equalTo(24)
        }
        textStack.snp.makeConstraints { make in
            make.leading.equalTo(icon.snp.trailing).offset(8)
            make.centerY.equalToSuperview()
        }
        reportButton.snp.makeConstraints { make in
            make.trailing.equalToSuperview().offset(-15)
            make.centerY.equalToSuperview()
            make.size.equalTo(72)
        }
        snp.makeConstraints { make in
            make.height.equalTo(96)
        }
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func setReporting(_ reporting: Bool) {
        reportButton.isEnabled = !reporting
        reportButton.alpha = reporting ? 0.6 : 1
    }

    @objc private func reportTapped() { onReportTap?() }
}

/// 底部快捷操作按钮。
final class LocationReportBottomActionView: UIControl {

    private let iconView = UIImageView()
    private let titleLabel = UILabel()

    init(title: String, symbol: String) {
        super.init(frame: .zero)
        backgroundColor = .white
        layer.cornerRadius = 10

        iconView.image = UIImage(systemName: symbol)
        iconView.tintColor = AppColor.primary
        iconView.contentMode = .scaleAspectFit

        titleLabel.text = title
        titleLabel.font = .systemFont(ofSize: 12)
        titleLabel.textColor = AppColor.textPrimary
        titleLabel.textAlignment = .center

        let stack = UIStackView(arrangedSubviews: [iconView, titleLabel])
        stack.axis = .vertical
        stack.spacing = 4
        stack.alignment = .center
        stack.isUserInteractionEnabled = false
        addSubview(stack)
        stack.snp.makeConstraints { make in
            make.center.equalToSuperview()
        }
        iconView.snp.makeConstraints { make in
            make.size.equalTo(24)
        }
        snp.makeConstraints { make in
            make.height.equalTo(80)
        }
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override var isSelected: Bool {
        didSet { applySelectedStyle() }
    }

    func applyOnlineStyle(isOnline: Bool) {
        if isOnline {
            backgroundColor = AppColor.online
            iconView.tintColor = .white
            titleLabel.text = "在线"
            titleLabel.textColor = .white
        } else {
            backgroundColor = .white
            iconView.tintColor = UIColor(hex: 0x7B8EAA)
            titleLabel.text = "离线"
            titleLabel.textColor = UIColor(hex: 0x7B8EAA)
        }
    }

    private func applySelectedStyle() {
        guard titleLabel.text == "标记上报" else { return }
        if isSelected {
            backgroundColor = AppColor.online
            iconView.tintColor = UIColor(hex: 0xF0FDF4)
            titleLabel.textColor = UIColor(hex: 0xF0FDF4)
        } else {
            backgroundColor = .white
            iconView.tintColor = AppColor.primary
            titleLabel.textColor = AppColor.textPrimary
        }
    }
}

/// 位置上报地图容器，模拟器使用 MapKit。
#if targetEnvironment(simulator)
final class LocationReportMapView: UIView, MKMapViewDelegate {

    var onMapTap: ((CLLocationCoordinate2D) -> Void)?

    let mapView: MKMapView
    private var markerAnnotation: MKPointAnnotation?
    private var shouldCenterOnNextUserLocation = false

    override init(frame: CGRect) {
        mapView = MKMapView(frame: .zero)
        super.init(frame: frame)
        mapView.delegate = self
        mapView.showsUserLocation = true
        mapView.showsCompass = false
        addSubview(mapView)
        mapView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(mapTapped(_:)))
        tapGesture.cancelsTouchesInView = false
        mapView.addGestureRecognizer(tapGesture)
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    /// 进入页面后，在首次拿到用户位置时将地图居中。
    func enableInitialUserLocationCentering() {
        shouldCenterOnNextUserLocation = true
        centerOnUserLocationIfNeeded()
    }

    func centerOnUserLocation() {
        guard let coordinate = validUserCoordinate else { return }
        setCenter(coordinate)
    }

    func setCenter(_ coordinate: CLLocationCoordinate2D, animated: Bool = true) {
        let region = MKCoordinateRegion(
            center: coordinate,
            span: MKCoordinateSpan(latitudeDelta: 0.012, longitudeDelta: 0.012)
        )
        mapView.setRegion(region, animated: animated)
    }

    func zoomIn() {
        updateZoom(scale: 0.5)
    }

    func zoomOut() {
        updateZoom(scale: 2)
    }

    func updateMarker(latitude: Double?, longitude: Double?) {
        if let markerAnnotation {
            mapView.removeAnnotation(markerAnnotation)
            self.markerAnnotation = nil
        }
        guard let latitude, let longitude else { return }
        let annotation = MKPointAnnotation()
        annotation.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        markerAnnotation = annotation
        mapView.addAnnotation(annotation)
    }

    func mapView(_ mapView: MKMapView, didUpdate userLocation: MKUserLocation) {
        centerOnUserLocationIfNeeded()
    }

    @objc private func mapTapped(_ gesture: UITapGestureRecognizer) {
        guard gesture.state == .ended else { return }
        let point = gesture.location(in: mapView)
        onMapTap?(mapView.convert(point, toCoordinateFrom: mapView))
    }

    private var validUserCoordinate: CLLocationCoordinate2D? {
        guard let coordinate = mapView.userLocation.location?.coordinate,
              CLLocationCoordinate2DIsValid(coordinate),
              coordinate.latitude != 0 || coordinate.longitude != 0 else {
            return nil
        }
        return coordinate
    }

    private func centerOnUserLocationIfNeeded() {
        guard shouldCenterOnNextUserLocation, let coordinate = validUserCoordinate else { return }
        setCenter(coordinate, animated: false)
        shouldCenterOnNextUserLocation = false
    }

    private func updateZoom(scale: Double) {
        let current = mapView.region
        let span = MKCoordinateSpan(
            latitudeDelta: min(max(current.span.latitudeDelta * scale, 0.0005), 120),
            longitudeDelta: min(max(current.span.longitudeDelta * scale, 0.0005), 120)
        )
        mapView.setRegion(MKCoordinateRegion(center: current.center, span: span), animated: true)
    }
}
#else
/// 位置上报地图容器，真机封装高德 `MAMapView`。
final class LocationReportMapView: UIView, MAMapViewDelegate {

    var onMapTap: ((CLLocationCoordinate2D) -> Void)?

    let mapView: MAMapView
    private var markerAnnotation: MAPointAnnotation?
    private var shouldCenterOnNextUserLocation = false

    override init(frame: CGRect) {
        _ = AMapBootstrap.configureIfNeeded()
        mapView = MAMapView(frame: .zero)
        super.init(frame: frame)
        mapView.delegate = self
        mapView.showsUserLocation = true
        mapView.showsCompass = false
        mapView.zoomLevel = 15
        addSubview(mapView)
        mapView.snp.makeConstraints { make in
            make.edges.equalToSuperview()
        }
    }

    @available(*, unavailable)
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    /// 进入页面后，在首次拿到用户位置时将地图居中（不持续跟随，便于手动拖动）。
    func enableInitialUserLocationCentering() {
        shouldCenterOnNextUserLocation = true
        centerOnUserLocationIfNeeded()
    }

    func centerOnUserLocation() {
        guard let coordinate = validUserCoordinate else { return }
        setCenter(coordinate)
    }

    func setCenter(_ coordinate: CLLocationCoordinate2D, animated: Bool = true) {
        mapView.setCenter(coordinate, animated: animated)
        mapView.setZoomLevel(15, animated: animated)
    }

    func zoomIn() {
        mapView.setZoomLevel(mapView.zoomLevel + 1, animated: true)
    }

    func zoomOut() {
        mapView.setZoomLevel(mapView.zoomLevel - 1, animated: true)
    }

    func updateMarker(latitude: Double?, longitude: Double?) {
        if let annotation = markerAnnotation {
            mapView.removeAnnotation(annotation)
            markerAnnotation = nil
        }
        guard let latitude, let longitude else { return }
        let annotation = MAPointAnnotation()
        annotation.coordinate = CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        markerAnnotation = annotation
        mapView.addAnnotation(annotation)
    }

    func mapView(_ mapView: MAMapView!, didUpdate userLocation: MAUserLocation!, updatingLocation: Bool) {
        guard updatingLocation else { return }
        centerOnUserLocationIfNeeded()
    }

    func mapView(_ mapView: MAMapView!, didSingleTappedAt coordinate: CLLocationCoordinate2D) {
        onMapTap?(coordinate)
    }

    private var validUserCoordinate: CLLocationCoordinate2D? {
        let coordinate = mapView.userLocation.location?.coordinate
        guard let coordinate, CLLocationCoordinate2DIsValid(coordinate) else { return nil }
        guard coordinate.latitude != 0 || coordinate.longitude != 0 else { return nil }
        return coordinate
    }

    private func centerOnUserLocationIfNeeded() {
        guard shouldCenterOnNextUserLocation, let coordinate = validUserCoordinate else { return }
        setCenter(coordinate, animated: false)
        shouldCenterOnNextUserLocation = false
    }
}
#endif
