//
//  LocationReportViewController.swift
//  suixinkan
//

import CoreLocation
import SnapKit
import UIKit

/// 位置上报独立页，对齐 Android `LocationReportScreen`。
final class LocationReportViewController: BaseViewController {

    private let viewModel: LocationReportViewModel
    private let homeAPI: HomeAPI

    private let mapContainer = LocationReportMapView()
    private let mapControls = LocationReportMapControlStack()
    private let statusCard = LocationReportStatusCardView()
    private let actionCard = LocationReportActionCardView()
    private let markButton = LocationReportBottomActionView(title: "标记上报", symbol: "mappin.and.ellipse")
    private let historyButton = LocationReportBottomActionView(title: "历史记录", symbol: "clock")
    private let onlineButton = LocationReportBottomActionView(title: "离线", symbol: "power")
    private var hasCenteredMap = false

    init(
        viewModel: LocationReportViewModel = LocationReportViewModel(),
        homeAPI: HomeAPI? = nil
    ) {
        self.viewModel = viewModel
        self.homeAPI = homeAPI ?? NetworkServices.shared.homeAPI
        super.init(nibName: nil, bundle: nil)
    }

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

    override func setupNavigationBar() {
        title = "位置上报"
    }

    override func setupUI() {
        view.backgroundColor = AppColor.pageBackground

        let bottomStack = UIStackView(arrangedSubviews: [markButton, historyButton, onlineButton])
        bottomStack.axis = .horizontal
        bottomStack.spacing = 12
        bottomStack.distribution = .fillEqually

        let panelStack = UIStackView(arrangedSubviews: [statusCard, actionCard, bottomStack])
        panelStack.axis = .vertical
        panelStack.spacing = 12

        view.addSubview(mapContainer)
        view.addSubview(mapControls)
        view.addSubview(panelStack)

        mapContainer.snp.makeConstraints { make in
            make.top.leading.trailing.equalTo(view.safeAreaLayoutGuide)
            make.height.equalTo(view.snp.height).multipliedBy(0.45)
        }
        mapControls.snp.makeConstraints { make in
            make.trailing.equalTo(mapContainer).offset(-16)
            make.centerY.equalTo(mapContainer)
        }
        panelStack.snp.makeConstraints { make in
            make.top.equalTo(mapContainer.snp.bottom).offset(-20)
            make.leading.trailing.equalToSuperview().inset(15)
            make.bottom.lessThanOrEqualTo(view.safeAreaLayoutGuide).offset(-12)
        }
    }

    override func bindActions() {
        viewModel.onStateChange = { [weak self] in
            Task { @MainActor in self?.applyViewModel() }
        }
        viewModel.onShowMessage = { [weak self] message in
            Task { @MainActor in self?.showToast(message) }
        }

        mapControls.onZoomIn = { [weak self] in self?.mapContainer.zoomIn() }
        mapControls.onZoomOut = { [weak self] in self?.mapContainer.zoomOut() }
        mapControls.onRelocate = { [weak self] in
            self?.mapContainer.centerOnUserLocation()
            self?.viewModel.startLocation()
        }
        mapContainer.onMapTap = { [weak self] coordinate in
            self?.viewModel.setMarkerLocation(latitude: coordinate.latitude, longitude: coordinate.longitude)
        }

        statusCard.onOnlineStatusTap = { [weak self] in self?.viewModel.showOnlineStatusSwitchDialog() }
        statusCard.onReminderTap = { [weak self] in
            guard let self else { return }
            LocationReportDialogPresenter.presentReminderPicker(from: self) { minutes in
                self.viewModel.updateReminderMinutes(minutes)
            }
        }
        actionCard.onReportTap = { [weak self] in
            guard let self else { return }
            Task { await self.viewModel.reportLocation(api: self.homeAPI) }
        }
        markButton.addTarget(self, action: #selector(markTapped), for: .touchUpInside)
        historyButton.addTarget(self, action: #selector(historyTapped), for: .touchUpInside)
        onlineButton.addTarget(self, action: #selector(onlineTapped), for: .touchUpInside)

        viewModel.restoreStateIfNeeded()
        mapContainer.enableInitialUserLocationCentering()
        requestLocationIfNeeded()
        applyViewModel()
    }

    private func requestLocationIfNeeded() {
        Task {
            do {
                try await LocationProvider.shared.ensureLocationPermission()
                mapContainer.enableInitialUserLocationCentering()
                viewModel.startLocation()
            } catch {
                showToast((error as? LocalizedError)?.errorDescription ?? error.localizedDescription)
            }
        }
    }

    private func applyViewModel() {
        statusCard.apply(
            isOnline: viewModel.isOnline,
            countdown: viewModel.countdownDisplayText,
            reminderMinutes: viewModel.reminderMinutes
        )
        actionCard.setReporting(viewModel.isReporting)
        markButton.isSelected = viewModel.isMarking
        onlineButton.applyOnlineStyle(isOnline: viewModel.isOnline)

        mapContainer.updateMarker(latitude: viewModel.markerLatitude, longitude: viewModel.markerLongitude)
        if !hasCenteredMap, let lat = viewModel.currentLatitude, let lng = viewModel.currentLongitude {
            mapContainer.setCenter(CLLocationCoordinate2D(latitude: lat, longitude: lng), animated: false)
            hasCenteredMap = true
        }

        if viewModel.showOnlineStatusDialog {
            viewModel.hideOnlineStatusSwitchDialog()
            LocationReportDialogPresenter.presentOnlineStatusSwitch(
                from: self,
                isOnline: viewModel.isOnline
            ) { [weak self] in
                guard let self else { return }
                Task { await self.viewModel.switchOnlineStatus(api: self.homeAPI) }
            }
        }

        if viewModel.showLocationReportSuccessDialog {
            let reportTime = viewModel.reportTimeText
            let countdown = viewModel.countdownDisplayText
            viewModel.hideLocationReportSuccessDialog()
            LocationReportDialogPresenter.presentReportSuccess(
                from: self,
                reportTime: reportTime,
                countdown: countdown
            )
        }
    }

    @objc private func markTapped() {
        viewModel.toggleMarking()
    }

    @objc private func historyTapped() {
        navigationController?.pushViewController(LocationReportHistoryViewController(), animated: true)
    }

    @objc private func onlineTapped() {
        viewModel.showOnlineStatusSwitchDialog()
    }
}
