//
//  ScenicQueueSettingsViews.swift
//  suixinkan
//
//  Created by Codex on 2026/6/25.
//

import SwiftUI

/// 排队设置页面。
struct ScenicQueueSettingsView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @EnvironmentObject private var scenicSpotContext: ScenicSpotContext
    @Environment(\.scenicQueueAPI) private var queueAPI
    @EnvironmentObject private var queueRuntime: ScenicQueueRuntime
    @EnvironmentObject private var toastCenter: ToastCenter
    @StateObject private var viewModel = ScenicQueueSettingsViewModel()
    @State private var selectedTab: ScenicQueueSettingsTab = .basic
    @State private var qrcodeURL: String?
    @State private var saving = false

    private var currentScenicId: Int? { accountContext.currentScenic?.id }
    private var currentUserId: String? { accountContext.profile?.userId }

    var body: some View {
        ScrollView {
            VStack(spacing: AppMetrics.Spacing.medium) {
                Picker("设置分组", selection: $selectedTab) {
                    ForEach(ScenicQueueSettingsTab.allCases) { tab in
                        Text(tab.title).tag(tab)
                    }
                }
                .pickerStyle(.segmented)

                switch selectedTab {
                case .basic:
                    basicSection
                case .notice:
                    noticeSection
                case .voice:
                    voiceSection
                case .logs:
                    logsSection
                }
            }
            .padding(AppMetrics.Spacing.pageHorizontal)
        }
        .background(Color(hex: 0xF5F7FA).ignoresSafeArea())
        .navigationTitle("排队设置")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItemGroup(placement: .topBarTrailing) {
                Button {
                    Task { await fetchQRCode() }
                } label: {
                    Image(systemName: "qrcode")
                }
                .accessibilityLabel("取号二维码")

                Button(saving ? "保存中" : "保存") {
                    Task { await save() }
                }
                .disabled(saving || viewModel.loading)
            }
        }
        .sheet(item: Binding(
            get: { qrcodeURL.map(QueueQRCodeSheetItem.init(url:)) },
            set: { qrcodeURL = $0?.url }
        )) { item in
            QueueQRCodeView(url: item.url) {
                await saveQRCode(url: item.url)
            }
        }
        .task(id: taskID) {
            await viewModel.load(api: queueAPI, scenicId: currentScenicId, userId: currentUserId, spots: scenicSpotContext.spots)
            await viewModel.loadSettingChangeLogs(api: queueAPI, scenicId: currentScenicId)
        }
        .onChange(of: viewModel.message) { message in
            if let message { toastCenter.show(message) }
        }
    }

    private var taskID: String {
        "\(currentScenicId ?? 0)-\(scenicSpotContext.spots.map(\.id).description)"
    }

    private var basicSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
            sectionTitle("基础设置")
            Picker("打卡点", selection: Binding(
                get: { viewModel.selectedSpotId ?? 0 },
                set: { id in
                    viewModel.selectedSpotId = id == 0 ? nil : id
                    Task { await viewModel.loadSelectedSpotSetting(api: queueAPI, scenicId: currentScenicId, userId: currentUserId) }
                }
            )) {
                Text("请选择").tag(0)
                ForEach(viewModel.scenicSpots) { spot in
                    Text(spot.name).tag(spot.id)
                }
            }
            .pickerStyle(.menu)
            .frame(maxWidth: .infinity, alignment: .leading)

            Toggle("开放排队", isOn: $viewModel.queueOpen)
            DatePicker("营业开始", selection: $viewModel.businessStartTime, displayedComponents: .hourAndMinute)
            DatePicker("营业结束", selection: $viewModel.businessEndTime, displayedComponents: .hourAndMinute)
            field("最大排队范围", text: $viewModel.maxQueueRangeKm, keyboard: .decimalPad, unit: "公里")
                .onChange(of: viewModel.maxQueueRangeKm) { value in viewModel.updateMaxQueueRange(value) }
            field("排队次数限制", text: $viewModel.localQueueLimit, keyboard: .numberPad, unit: "次")
            field("过号顺延", text: $viewModel.localPassDelay, keyboard: .numberPad, unit: "位")
            field("拍摄分钟", text: $viewModel.photoEstimateMin, keyboard: .numberPad, unit: "分")
            field("拍摄秒数", text: $viewModel.photoEstimateSec, keyboard: .numberPad, unit: "秒")
            Toggle("展示开始拍摄按钮", isOn: $viewModel.showStartShootingButton)
            field("自动叫号后续", text: $viewModel.autoCallAheadCount, keyboard: .numberPad, unit: "位")
            Toggle("快捷叫号按钮", isOn: $viewModel.quickCallButtonEnabled)
            Toggle("预备叫号按钮", isOn: $viewModel.prepareCallButtonEnabled)
        }
        .cardStyle()
    }

    private var noticeSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
            sectionTitle("通知规则")
            field("第一次通知阈值", text: $viewModel.firstAhead, keyboard: .numberPad, unit: "位")
            Toggle("第一次短信通知", isOn: $viewModel.firstSms)
            Toggle("第一次电话通知", isOn: $viewModel.firstPhone)
            Divider()
            field("第二次通知阈值", text: $viewModel.secondAhead, keyboard: .numberPad, unit: "位")
            Toggle("第二次短信通知", isOn: $viewModel.secondSms)
            Toggle("第二次电话通知", isOn: $viewModel.secondPhone)
        }
        .cardStyle()
    }

    private var voiceSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
            sectionTitle("语音播报")
            Toggle("本地语音合成提醒", isOn: Binding(
                get: { queueRuntime.voiceEnabled },
                set: { queueRuntime.voiceEnabled = $0 }
            ))
            Toggle("后台短时轮询", isOn: Binding(
                get: { queueRuntime.backgroundPollingEnabled },
                set: { queueRuntime.backgroundPollingEnabled = $0 }
            ))
            field("播报间隔", text: $viewModel.broadcastIntervalSec, keyboard: .numberPad, unit: "秒")
            field("读秒阈值", text: $viewModel.countdownThresholdSec, keyboard: .numberPad, unit: "秒")

            TextEditor(text: $viewModel.customTtsText)
                .frame(minHeight: 88)
                .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: 88)
            HStack {
                Button("试听") { viewModel.playCustomText() }
                    .buttonStyle(.bordered)
                Button("保存为预设") { viewModel.saveCustomTextAsPreset() }
                    .buttonStyle(.borderedProminent)
            }
            Button("播放测试音") { viewModel.playTestSound() }
                .buttonStyle(.bordered)

            if !viewModel.presetVoices.isEmpty {
                ForEach(Array(viewModel.presetVoices.enumerated()), id: \.offset) { index, text in
                    HStack {
                        Text(text)
                            .font(.system(size: AppMetrics.FontSize.subheadline))
                            .foregroundStyle(AppDesign.textPrimary)
                            .lineLimit(2)
                        Spacer()
                        Button {
                            viewModel.deletePresetVoice(at: index)
                        } label: {
                            Image(systemName: "trash")
                        }
                    }
                    .padding(.vertical, 6)
                }
            }
        }
        .cardStyle()
    }

    private var logsSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
            HStack {
                sectionTitle("配置日志")
                Spacer()
                Button {
                    Task { await viewModel.loadSettingChangeLogs(api: queueAPI, scenicId: currentScenicId) }
                } label: {
                    Image(systemName: "arrow.clockwise")
                }
            }
            if viewModel.logs.isEmpty {
                AppContentUnavailableView("暂无配置日志", systemImage: "clock.arrow.circlepath")
                    .frame(maxWidth: .infinity, minHeight: 180)
            } else {
                ForEach(viewModel.logs) { log in
                    VStack(alignment: .leading, spacing: 6) {
                        Text(log.displayText.isEmpty ? log.summary : log.displayText)
                            .font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
                            .foregroundStyle(AppDesign.textPrimary)
                        Text("\(log.scenicSpotName) \(log.operatorName) \(log.createdAt)")
                            .font(.system(size: AppMetrics.FontSize.caption))
                            .foregroundStyle(AppDesign.textSecondary)
                    }
                    .frame(maxWidth: .infinity, alignment: .leading)
                    Divider()
                }
            }
        }
        .cardStyle()
    }

    private func field(_ title: String, text: Binding<String>, keyboard: UIKeyboardType, unit: String) -> some View {
        HStack(spacing: AppMetrics.Spacing.medium) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textPrimary)
                .frame(width: 104, alignment: .leading)
            TextField("", text: text)
                .keyboardType(keyboard)
                .textFieldStyle(.plain)
                .multilineTextAlignment(.trailing)
            Text(unit)
                .font(.system(size: AppMetrics.FontSize.caption))
                .foregroundStyle(AppDesign.textSecondary)
        }
        .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)
    }

    private func sectionTitle(_ title: String) -> some View {
        Text(title)
            .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
            .foregroundStyle(AppDesign.textPrimary)
    }

    private func fetchQRCode() async {
        do {
            qrcodeURL = try await viewModel.fetchQRCode(api: queueAPI, scenicId: currentScenicId)
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    private func saveQRCode(url: String) async {
        do {
            try await viewModel.saveQRCodeToPhotoLibrary(qrcodeURL: url)
            toastCenter.show("二维码已保存")
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    private func save() async {
        saving = true
        defer { saving = false }
        do {
            try await viewModel.save(api: queueAPI, scenicId: currentScenicId, userId: currentUserId)
            toastCenter.show("排队设置已保存")
            await viewModel.loadSettingChangeLogs(api: queueAPI, scenicId: currentScenicId)
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }
}

private enum ScenicQueueSettingsTab: CaseIterable, Identifiable {
    case basic
    case notice
    case voice
    case logs

    var id: Self { self }

    var title: String {
        switch self {
        case .basic: return "基础"
        case .notice: return "通知"
        case .voice: return "语音"
        case .logs: return "日志"
        }
    }
}

private struct QueueQRCodeSheetItem: Identifiable {
    let url: String
    var id: String { url }
}

private struct QueueQRCodeView: View {
    let url: String
    let onSave: () async -> Void
    @Environment(\.dismiss) private var dismiss
    @State private var saving = false

    var body: some View {
        NavigationStack {
            VStack(spacing: AppMetrics.Spacing.large) {
                RemoteImage(urlString: url, contentMode: .fit) {
                    Image(systemName: "qrcode")
                        .font(.system(size: 80))
                        .foregroundStyle(AppDesign.placeholder)
                }
                .frame(maxWidth: .infinity)
                .frame(height: 280)
                .padding(AppMetrics.Spacing.large)
                .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))

                Button {
                    Task {
                        saving = true
                        await onSave()
                        saving = false
                    }
                } label: {
                    Label(saving ? "保存中" : "保存到相册", systemImage: "square.and.arrow.down")
                        .frame(maxWidth: .infinity)
                        .frame(height: AppMetrics.ControlSize.primaryButtonHeight)
                }
                .buttonStyle(.borderedProminent)
                .disabled(saving)
            }
            .padding(AppMetrics.Spacing.pageHorizontal)
            .background(Color(hex: 0xF5F7FA).ignoresSafeArea())
            .navigationTitle("取号二维码")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("关闭") { dismiss() }
                }
            }
        }
    }
}

private extension View {
    func cardStyle() -> some View {
        padding(AppMetrics.Spacing.medium)
            .frame(maxWidth: .infinity, alignment: .leading)
            .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }
}
