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

import SwiftUI

/// 排队管理首页，展示当前打卡点队列和操作入口。
struct QueueManagementView: 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 = QueueManagementViewModel()
    @State private var pendingAction: QueueActionConfirmation?
    @State private var markTarget: QueueItem?
    @State private var processingId: Int64?

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

    var body: some View {
        ScrollView {
            VStack(spacing: AppMetrics.Spacing.medium) {
                header
                if currentScenicId == nil {
                    AppContentUnavailableView("请先选择景区", systemImage: "map", description: Text("排队管理需要当前景区上下文"))
                        .frame(minHeight: 260)
                } else if !viewModel.queueGatePassed {
                    gateCard
                } else {
                    listSection
                }
            }
            .padding(AppMetrics.Spacing.pageHorizontal)
        }
        .background(Color(hex: 0xF5F7FA).ignoresSafeArea())
        .navigationTitle("排队管理")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                NavigationLink {
                    ScenicQueueSettingsView()
                } label: {
                    Image(systemName: "gearshape")
                }
                .accessibilityLabel("排队设置")
            }
        }
        .alert(item: $pendingAction) { action in
            Alert(
                title: Text(action.title),
                message: Text(action.message),
                primaryButton: .default(Text("确认")) {
                    Task { await perform(action) }
                },
                secondaryButton: .cancel()
            )
        }
        .sheet(item: $markTarget) { item in
            QueueUserMarkView(item: item) { markAsFreelance, banDays in
                await userMark(item: item, markAsFreelance: markAsFreelance, banDays: banDays)
            }
        }
        .task(id: reloadTaskID) {
            await reload()
            await viewModel.startRealtime(api: queueAPI, scenicId: currentScenicId, userId: currentUserId)
        }
        .onAppear {
            queueRuntime.setSuspendedByQueueScreen(true)
        }
        .onDisappear {
            viewModel.stopRealtime()
            queueRuntime.setSuspendedByQueueScreen(false)
        }
        .refreshable {
            await reload()
        }
        .onChange(of: viewModel.remoteCallAnnouncement) { announcement in
            if let announcement {
                toastCenter.show("远端已叫号 \(announcement.queueCode.isEmpty ? "当前游客" : announcement.queueCode)")
            }
        }
        .onChange(of: viewModel.errorMessage) { message in
            if let message { toastCenter.show(message) }
        }
    }

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

    private var header: some View {
        VStack(spacing: AppMetrics.Spacing.medium) {
            HStack(spacing: AppMetrics.Spacing.medium) {
                metricCard(title: "在排人数", value: "\(viewModel.queueCount)", icon: "person.3.fill", color: AppDesign.primary)
                metricCard(title: "平均等待", value: "\(viewModel.avgWaitMinText) 分", icon: "clock.fill", color: AppDesign.warning)
            }

            HStack {
                VStack(alignment: .leading, spacing: 4) {
                    Text(accountContext.currentScenic?.name ?? "未选择景区")
                        .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                        .foregroundStyle(AppDesign.textPrimary)
                    Text("打卡点：\(viewModel.currentSpotName)")
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                        .foregroundStyle(AppDesign.textSecondary)
                }
                Spacer()
                Text(viewModel.lastSyncTimeText)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }
            .padding(AppMetrics.Spacing.medium)
            .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
        }
    }

    private var gateCard: some View {
        VStack(spacing: AppMetrics.Spacing.medium) {
            Image(systemName: "mappin.and.ellipse")
                .font(.system(size: 42, weight: .semibold))
                .foregroundStyle(AppDesign.primary)
            Text("请先设置排队打卡点")
                .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                .foregroundStyle(AppDesign.textPrimary)
            Text("排队列表需要固定打卡点后才能加载。")
                .font(.system(size: AppMetrics.FontSize.subheadline))
                .foregroundStyle(AppDesign.textSecondary)
            NavigationLink {
                ScenicQueueSettingsView()
            } label: {
                Label("前往设置", systemImage: "gearshape")
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .frame(maxWidth: .infinity)
                    .frame(height: AppMetrics.ControlSize.primaryButtonHeight)
            }
            .buttonStyle(.borderedProminent)
        }
        .padding(AppMetrics.Spacing.large)
        .frame(maxWidth: .infinity)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    private var listSection: some View {
        VStack(spacing: AppMetrics.Spacing.medium) {
            Picker("排队类型", selection: Binding(
                get: { viewModel.selectedListType },
                set: { type in
                    Task { await viewModel.selectListType(type, api: queueAPI, scenicId: currentScenicId, userId: currentUserId) }
                }
            )) {
                ForEach(QueueListType.allCases) { type in
                    Text(type.title).tag(type)
                }
            }
            .pickerStyle(.segmented)

            if viewModel.loading && viewModel.items.isEmpty {
                ProgressView("加载中...")
                    .frame(maxWidth: .infinity, minHeight: 240)
            } else if viewModel.items.isEmpty {
                AppContentUnavailableView(viewModel.selectedListType.emptyText, systemImage: "person.crop.circle.badge.questionmark")
                    .frame(maxWidth: .infinity, minHeight: 240)
                    .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
            } else {
                LazyVStack(spacing: AppMetrics.Spacing.medium) {
                    ForEach(Array(viewModel.items.enumerated()), id: \.element.id) { index, item in
                        QueueTicketCard(
                            item: item,
                            index: index + 1,
                            listType: viewModel.selectedListType,
                            processing: processingId == item.id,
                            onCall: { pendingAction = QueueActionConfirmation(kind: item.isCalled == 1 ? .recall : .call, item: item) },
                            onPass: { pendingAction = QueueActionConfirmation(kind: .pass, item: item) },
                            onFinish: { pendingAction = QueueActionConfirmation(kind: .finish, item: item) },
                            onRequeue: { pendingAction = QueueActionConfirmation(kind: .requeue, item: item) },
                            onMark: { markTarget = item }
                        )
                        .onAppear {
                            if item.id == viewModel.items.last?.id {
                                Task { await viewModel.loadMore(api: queueAPI, scenicId: currentScenicId, userId: currentUserId) }
                            }
                        }
                    }
                    if viewModel.loadingMore {
                        ProgressView()
                            .frame(maxWidth: .infinity)
                            .padding(.vertical, AppMetrics.Spacing.medium)
                    }
                }
            }
        }
    }

    private func metricCard(title: String, value: String, icon: String, color: Color) -> some View {
        HStack(spacing: AppMetrics.Spacing.medium) {
            Image(systemName: icon)
                .font(.system(size: 22, weight: .bold))
                .foregroundStyle(color)
                .frame(width: 38, height: 38)
                .background(color.opacity(0.12), in: RoundedRectangle(cornerRadius: 8))
            VStack(alignment: .leading, spacing: 3) {
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
                Text(value)
                    .font(.system(size: AppMetrics.FontSize.title3, weight: .bold))
                    .foregroundStyle(AppDesign.textPrimary)
                    .lineLimit(1)
                    .minimumScaleFactor(0.75)
            }
        }
        .frame(maxWidth: .infinity, alignment: .leading)
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    private func reload() async {
        await viewModel.reload(
            api: queueAPI,
            scenicId: currentScenicId,
            userId: currentUserId,
            spots: scenicSpotContext.spots
        )
    }

    private func perform(_ action: QueueActionConfirmation) async {
        processingId = action.item.id
        defer { processingId = nil }
        do {
            switch action.kind {
            case .call, .recall:
                try await viewModel.callQueue(api: queueAPI, id: action.item.id)
            case .pass:
                try await viewModel.passQueue(api: queueAPI, scenicId: currentScenicId, userId: currentUserId, id: action.item.id)
            case .finish:
                _ = try await viewModel.finishQueue(api: queueAPI, scenicId: currentScenicId, userId: currentUserId, id: action.item.id)
            case .requeue:
                try await viewModel.requeue(api: queueAPI, scenicId: currentScenicId, userId: currentUserId, id: action.item.id, operatorId: Int(currentUserId ?? "") ?? 0)
            }
        } catch {
            toastCenter.show(error.localizedDescription)
        }
    }

    private func userMark(item: QueueItem, markAsFreelance: Bool, banDays: Int) async -> Bool {
        guard let scenicId = currentScenicId else { return false }
        processingId = item.id
        defer { processingId = nil }
        do {
            try await viewModel.userMark(
                api: queueAPI,
                scenicId: scenicId,
                userId: currentUserId,
                request: ScenicQueueUserMarkRequest(
                    uid: item.uid,
                    scenicId: Int64(scenicId),
                    markAsFreelancePhotog: markAsFreelance ? 1 : 0,
                    queueBanDays: markAsFreelance ? banDays : nil,
                    operatorId: Int(currentUserId ?? "")
                )
            )
            return true
        } catch {
            toastCenter.show(error.localizedDescription)
            return false
        }
    }
}

private struct QueueTicketCard: View {
    let item: QueueItem
    let index: Int
    let listType: QueueListType
    let processing: Bool
    let onCall: () -> Void
    let onPass: () -> Void
    let onFinish: () -> Void
    let onRequeue: () -> Void
    let onMark: () -> Void

    var body: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.medium) {
            HStack(alignment: .top) {
                VStack(alignment: .leading, spacing: 6) {
                    HStack(spacing: 8) {
                        Text(item.queueCode.isEmpty ? "\(index)" : item.queueCode)
                            .font(.system(size: 26, weight: .bold))
                            .foregroundStyle(AppDesign.textPrimary)
                        if item.isCalled == 1 || item.statusText.contains("已叫号") {
                            tag("已叫号", color: AppDesign.primary)
                        }
                        if item.shouldShowIdentityTag {
                            tag(item.identityTag, color: AppDesign.warning)
                        }
                    }
                    Text(item.phoneMasked)
                        .font(.system(size: AppMetrics.FontSize.subheadline))
                        .foregroundStyle(AppDesign.textSecondary)
                }
                Spacer()
                VStack(alignment: .trailing, spacing: 5) {
                    Text(item.statusText.isEmpty ? "--" : item.statusText)
                        .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                        .foregroundStyle(AppDesign.primary)
                    Text(item.queueTimeDisplay)
                        .font(.system(size: AppMetrics.FontSize.caption))
                        .foregroundStyle(AppDesign.textSecondary)
                }
            }

            HStack(spacing: AppMetrics.Spacing.small) {
                info("等待", "\(item.waitMin)分")
                info("前方", "\(item.aheadCount)位")
                info("今日", "\(item.queueCountToday)次")
            }

            if !item.queueBanLabel.isEmpty || item.isMissRequeueRecord {
                HStack(spacing: 8) {
                    if !item.queueBanLabel.isEmpty {
                        tag(item.queueBanLabel, color: AppDesign.warning)
                    }
                    if item.isMissRequeueRecord {
                        tag(item.missRequeueText.isEmpty ? "重排" : item.missRequeueText, color: AppDesign.warning)
                    }
                }
            }

            HStack(spacing: AppMetrics.Spacing.small) {
                if listType == .queueing {
                    actionButton(item.isCalled == 1 ? "重叫" : "叫号", icon: "speaker.wave.2.fill", action: onCall)
                    actionButton("过号", icon: "forward.end.fill", action: onPass)
                    actionButton("完成", icon: "checkmark.circle.fill", action: onFinish)
                } else {
                    actionButton("重排", icon: "arrow.uturn.left", action: onRequeue)
                }
                actionButton("标记", icon: "person.badge.key.fill", action: onMark)
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
        .opacity(processing ? 0.6 : 1)
    }

    private func info(_ title: String, _ value: String) -> some View {
        VStack(spacing: 4) {
            Text(title)
                .font(.system(size: AppMetrics.FontSize.caption))
                .foregroundStyle(AppDesign.textSecondary)
            Text(value)
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(AppDesign.textPrimary)
        }
        .frame(maxWidth: .infinity)
        .padding(.vertical, 8)
        .background(Color(hex: 0xF8FAFC), in: RoundedRectangle(cornerRadius: 8))
    }

    private func tag(_ text: String, color: Color) -> some View {
        Text(text)
            .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
            .foregroundStyle(color)
            .padding(.horizontal, 8)
            .padding(.vertical, 4)
            .background(color.opacity(0.12), in: Capsule())
    }

    private func actionButton(_ title: String, icon: String, action: @escaping () -> Void) -> some View {
        Button(action: action) {
            Label(title, systemImage: icon)
                .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                .frame(maxWidth: .infinity)
                .frame(height: 36)
        }
        .buttonStyle(.bordered)
    }
}

private struct QueueUserMarkView: View {
    let item: QueueItem
    let onConfirm: (Bool, Int) async -> Bool
    @Environment(\.dismiss) private var dismiss
    @State private var markAsFreelance = true
    @State private var queueBanDays = 7
    @State private var submitting = false

    var body: some View {
        NavigationStack {
            Form {
                Section("用户") {
                    Text(item.queueCode.isEmpty ? "当前游客" : item.queueCode)
                    Text(item.phoneMasked)
                }
                Section("标记") {
                    Toggle("标记为打野摄影师", isOn: $markAsFreelance)
                    Stepper("限制排队 \(queueBanDays) 天", value: $queueBanDays, in: 0...999)
                }
            }
            .navigationTitle("用户标记")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .cancellationAction) {
                    Button("取消") { dismiss() }
                }
                ToolbarItem(placement: .confirmationAction) {
                    Button(submitting ? "提交中" : "提交") {
                        Task {
                            submitting = true
                            let ok = await onConfirm(markAsFreelance, queueBanDays)
                            submitting = false
                            if ok { dismiss() }
                        }
                    }
                    .disabled(submitting)
                }
            }
        }
    }
}

private struct QueueActionConfirmation: Identifiable {
    enum Kind {
        case call
        case recall
        case pass
        case finish
        case requeue
    }

    let kind: Kind
    let item: QueueItem

    var id: String { "\(kind)-\(item.id)" }

    var title: String {
        switch kind {
        case .call: return "确认叫号"
        case .recall: return "确认重新叫号"
        case .pass: return "确认过号"
        case .finish: return "确认完成"
        case .requeue: return "确认重新排队"
        }
    }

    var message: String {
        let queueCode = item.queueCode.isEmpty ? "该游客" : item.queueCode
        switch kind {
        case .call:
            return "确定要叫号 \(queueCode) 吗？"
        case .recall:
            return "确定要重新叫号 \(queueCode) 吗？"
        case .pass:
            return "确定将 \(queueCode) 标记为过号吗？"
        case .finish:
            return "确定 \(queueCode) 已完成拍摄吗？"
        case .requeue:
            return "确定将 \(queueCode) 重新插入当前排队队列吗？"
        }
    }
}
