//
//  LocationReportViews.swift
//  suixinkan
//
//  Created by Codex on 2026/6/24.
//

import Combine
import SwiftUI

/// 位置上报页面，支持当前位置上报、标记点上报、在线状态和提醒设置。
struct LocationReportView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @EnvironmentObject private var homeLocationViewModel: HomeLocationViewModel
    @Environment(\.accountSnapshotStore) private var snapshotStore
    @Environment(\.locationReportAPI) private var locationReportAPI
    @EnvironmentObject private var router: RouterPath
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel = LocationReportViewModel()
    @State private var locationProvider = ForegroundLocationProvider()
    @State private var showOnlineDialog = false
    private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()

    var body: some View {
        ScrollView {
            VStack(spacing: AppMetrics.Spacing.medium) {
                statusSection
                currentLocationSection
                markedLocationSection
                reminderSection
                actionSection
            }
            .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.medium)
        }
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle("位置上报")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                Button {
                    router.navigate(to: .home(.locationReportHistory))
                } label: {
                    Image(systemName: "clock.arrow.circlepath")
                }
                .accessibilityLabel("上报历史")
            }
        }
        .onReceive(timer) { _ in homeLocationViewModel.tick() }
        .task {
            homeLocationViewModel.restoreState()
            guard viewModel.currentCoordinate == nil else { return }
            await locateCurrent()
        }
        .alert("切换在线状态", isPresented: $showOnlineDialog) {
            Button("取消", role: .cancel) {}
            Button("确定") {
                Task {
                    await globalLoading.withLoading(message: "获取定位中", showsMessage: true) {
                        await homeLocationViewModel.confirmOnlineToggle(
                            staffId: staffId,
                            scenicId: scenicId,
                            toast: toastCenter
                        )
                    }
                }
            }
        } message: {
            Text(homeLocationViewModel.isOnline ? "是否确认切换为离线状态？离线后将暂停位置上报。" : "是否确认切换为在线状态？在线后将开始位置上报和计时。")
        }
    }

    /// 在线状态和倒计时区域。
    private var statusSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
                    Text(homeLocationViewModel.isOnline ? "当前在线" : "当前离线")
                        .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                        .foregroundStyle(AppDesign.textPrimary)
                    Text(countdownText)
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                        .foregroundStyle(AppDesign.textSecondary)
                }
                Spacer()
                Button {
                    showOnlineDialog = true
                } label: {
                    Text(homeLocationViewModel.isOnline ? "在线" : "离线")
                        .font(.system(size: AppMetrics.FontSize.caption, weight: .medium))
                        .foregroundStyle(homeLocationViewModel.isOnline ? Color(hex: 0xF0FDF4) : Color(hex: 0x7B8EAA))
                        .padding(.horizontal, AppMetrics.Spacing.small)
                        .padding(.vertical, AppMetrics.Spacing.xxSmall + 2)
                        .background(homeLocationViewModel.isOnline ? Color(hex: 0x22C55E) : Color(hex: 0xF4F4F4), in: RoundedRectangle(cornerRadius: 4))
                }
                .buttonStyle(.plain)
            }
            if !homeLocationViewModel.reportTimeText.isEmpty {
                Text("上次上报：\(homeLocationViewModel.reportTimeText)")
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.placeholder)
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    private var countdownText: String {
        guard homeLocationViewModel.secondsUntilReport > 0 else { return "可立即上报" }
        let hours = homeLocationViewModel.secondsUntilReport / 3600
        let minutes = (homeLocationViewModel.secondsUntilReport % 3600) / 60
        return "\(hours)小时\(minutes)分钟后可再次提醒"
    }

    /// 当前定位区域。
    private var currentLocationSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text("当前位置")
                    .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                Spacer()
                Button("重新定位") {
                    Task { await locateCurrent() }
                }
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
            }
            locationText(coordinate: viewModel.currentCoordinate, address: viewModel.currentAddress)
            TextField("当前位置地址", text: $viewModel.currentAddress)
                .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 标记点区域。
    private var markedLocationSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text("标记点")
                    .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                Spacer()
                Button("使用当前位置") {
                    if let coordinate = viewModel.currentCoordinate {
                        viewModel.applyMarkedLocation(
                            latitude: coordinate.latitude,
                            longitude: coordinate.longitude,
                            address: viewModel.currentAddress
                        )
                    }
                }
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
            }
            locationText(coordinate: viewModel.markedCoordinate, address: viewModel.markedAddress)
            HStack(spacing: AppMetrics.Spacing.small) {
                TextField("纬度", text: Binding(
                    get: { viewModel.markedCoordinate.map { String($0.latitude) } ?? "" },
                    set: { text in updateMarkedCoordinate(latitudeText: text, longitudeText: nil) }
                ))
                .keyboardType(.decimalPad)
                .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)
                TextField("经度", text: Binding(
                    get: { viewModel.markedCoordinate.map { String($0.longitude) } ?? "" },
                    set: { text in updateMarkedCoordinate(latitudeText: nil, longitudeText: text) }
                ))
                .keyboardType(.decimalPad)
                .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)
            }
            TextField("标记点地址", text: $viewModel.markedAddress)
                .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 提醒设置区域。
    private var reminderSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            Text("提醒设置")
                .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
            ReminderTimeOptionsMenu(onSelect: { homeLocationViewModel.updateReminderMinutes($0) }) {
                Text(homeLocationViewModel.reminderMinutes == 0 ? "不提醒" : "提前 \(homeLocationViewModel.reminderMinutes) 分钟提醒")
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.primary)
            }
            .buttonStyle(.plain)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 上报按钮区域。
    private var actionSection: some View {
        VStack(spacing: AppMetrics.Spacing.small) {
            Button {
                Task { await submit(type: .immediate) }
            } label: {
                Label("立即上报当前位置", systemImage: "location.fill")
                    .frame(maxWidth: .infinity)
                    .frame(height: AppMetrics.ControlSize.primaryButtonHeight)
            }
            .buttonStyle(.borderedProminent)

            Button {
                Task { await submit(type: .marked) }
            } label: {
                Label("上报标记点", systemImage: "mappin.and.ellipse")
                    .frame(maxWidth: .infinity)
                    .frame(height: AppMetrics.ControlSize.primaryButtonHeight)
            }
            .buttonStyle(.bordered)
        }
        .disabled(viewModel.isSubmitting || homeLocationViewModel.isReporting)
    }

    /// 坐标和地址展示。
    private func locationText(coordinate: LocationCoordinate?, address: String) -> some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
            Text(address.isEmpty ? "暂无地址" : address)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textPrimary)
            Text(coordinate.map { "\($0.latitude), \($0.longitude)" } ?? "暂无坐标")
                .font(.system(size: AppMetrics.FontSize.caption))
                .foregroundStyle(AppDesign.textSecondary)
        }
        .frame(maxWidth: .infinity, alignment: .leading)
    }

    private var staffId: Int? {
        snapshotStore.load()?.businessUserId
    }

    private var scenicId: Int? {
        accountContext.currentScenic?.id
    }

    /// 请求当前位置。
    private func locateCurrent() async {
        do {
            let result = try await locationProvider.requestCurrentLocation()
            viewModel.applyCurrentLocation(latitude: result.latitude, longitude: result.longitude, address: result.address)
        } catch {
            toastCenter.show("定位失败：\(error.localizedDescription)")
        }
    }

    /// 提交指定类型的位置上报。
    private func submit(type: LocationReportType) async {
        let success = await globalLoading.withLoading {
            await viewModel.submit(
                type: type,
                staffId: staffId,
                scenicId: scenicId,
                homeLocationViewModel: homeLocationViewModel,
                toast: toastCenter
            )
        }
        toastCenter.show(success ? "上报成功" : (viewModel.errorMessage ?? "上报失败"))
    }

    /// 手动更新标记点经纬度。
    private func updateMarkedCoordinate(latitudeText: String?, longitudeText: String?) {
        let current = viewModel.markedCoordinate
        let latitude = Double(latitudeText ?? current.map { String($0.latitude) } ?? "")
        let longitude = Double(longitudeText ?? current.map { String($0.longitude) } ?? "")
        if let latitude, let longitude {
            viewModel.applyMarkedLocation(latitude: latitude, longitude: longitude, address: viewModel.markedAddress)
        }
    }
}

/// 位置上报历史页面，展示历史记录筛选和分页。
struct LocationReportHistoryView: View {
    @Environment(\.accountSnapshotStore) private var snapshotStore
    @Environment(\.locationReportAPI) private var locationReportAPI
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel = LocationReportHistoryViewModel()

    var body: some View {
        ScrollView {
            LazyVStack(spacing: AppMetrics.Spacing.medium) {
                filterSection
                contentSection
            }
            .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.medium)
        }
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle("位置上报历史")
        .navigationBarTitleDisplayMode(.inline)
        .refreshable { await reload(showLoading: false) }
        .task {
            guard viewModel.items.isEmpty else { return }
            await reload(showLoading: true)
        }
    }

    /// 筛选区域。
    private var filterSection: some View {
        VStack(spacing: AppMetrics.Spacing.small) {
            Picker("上报类型", selection: $viewModel.selectedType) {
                ForEach(LocationReportType.allCases) { type in
                    Text(type.title).tag(type)
                }
            }
            .pickerStyle(.segmented)
            .onChange(of: viewModel.selectedType) { _ in
                Task { await reload(showLoading: true) }
            }

            HStack(spacing: AppMetrics.Spacing.small) {
                optionalDatePicker(title: "开始", date: $viewModel.startDate)
                optionalDatePicker(title: "结束", date: $viewModel.endDate)
            }
            HStack {
                Button("清除日期") {
                    viewModel.startDate = nil
                    viewModel.endDate = nil
                    Task { await reload(showLoading: true) }
                }
                .foregroundStyle(AppDesign.textSecondary)
                Spacer()
                Button("应用日期") {
                    Task { await reload(showLoading: true) }
                }
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(AppDesign.primary)
            }
            .font(.system(size: AppMetrics.FontSize.subheadline))
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 内容区域。
    @ViewBuilder
    private var contentSection: some View {
        if viewModel.items.isEmpty {
            LocationReportEmptyState(title: "暂无历史记录", message: viewModel.errorMessage ?? "当前筛选条件下没有位置上报记录。")
        } else {
            ForEach(viewModel.items) { item in
                LocationReportHistoryCard(item: item)
                    .onAppear {
                        guard item.id == viewModel.items.last?.id else { return }
                        Task { await viewModel.loadMore(staffId: staffId, api: locationReportAPI) }
                    }
            }
            if viewModel.isLoadingMore {
                ProgressView()
                    .padding(.vertical, AppMetrics.Spacing.medium)
            }
        }
    }

    private var staffId: Int? {
        snapshotStore.load()?.businessUserId
    }

    /// 重新加载历史。
    private func reload(showLoading: Bool) async {
        await globalLoading.withOptionalLoading(showLoading) {
            await viewModel.reload(staffId: staffId, api: locationReportAPI)
        }
        if let error = viewModel.errorMessage {
            toastCenter.show(error)
        }
    }

    /// 可选日期选择器。
    private func optionalDatePicker(title: String, date: Binding<Date?>) -> some View {
        DatePicker(
            title,
            selection: Binding(
                get: { date.wrappedValue ?? Date() },
                set: { date.wrappedValue = $0 }
            ),
            displayedComponents: .date
        )
        .font(.system(size: AppMetrics.FontSize.subheadline))
    }
}

/// 位置上报历史卡片。
private struct LocationReportHistoryCard: View {
    let item: LocationReportHistoryItem

    var body: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text(item.typeTitle)
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                Spacer()
                Text(item.createdAt)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.placeholder)
            }
            Text(item.address.isEmpty ? "暂无地址" : item.address)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textSecondary)
            Text("\(item.latitude), \(item.longitude)")
                .font(.system(size: AppMetrics.FontSize.caption))
                .foregroundStyle(AppDesign.placeholder)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }
}

/// 位置上报空状态组件。
private struct LocationReportEmptyState: View {
    let title: String
    let message: String

    var body: some View {
        VStack(spacing: AppMetrics.Spacing.small) {
            Image(systemName: "location.slash")
                .font(.system(size: 34, weight: .semibold))
                .foregroundStyle(AppDesign.placeholder)
            Text(title)
                .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                .foregroundStyle(AppDesign.textPrimary)
            Text(message)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textSecondary)
                .multilineTextAlignment(.center)
        }
        .frame(maxWidth: .infinity)
        .padding(AppMetrics.Spacing.xLarge)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }
}
