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

import PhotosUI
import SwiftUI
import UniformTypeIdentifiers

/// 多点旅拍任务上传页面，负责选择打卡点和素材后提交到订单接口。
struct MultiTravelTaskUploadView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.ordersAPI) private var ordersAPI
    @Environment(\.ossUploadService) private var uploadService
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.dismiss) private var dismiss
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel: MultiTravelTaskUploadViewModel
    @State private var showSpotPicker = false
    @State private var showCloudSelection = false
    @State private var pickerItems: [PhotosPickerItem] = []

    /// 使用订单号初始化任务上传页面。
    init(initialOrderNumber: String) {
        _viewModel = StateObject(wrappedValue: MultiTravelTaskUploadViewModel(initialOrderNumber: initialOrderNumber))
    }

    var body: some View {
        ScrollView {
            VStack(spacing: AppMetrics.Spacing.medium) {
                orderSection
                cloudFileSection
                localFileSection
                submitButton
            }
            .padding(AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.medium)
        }
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle("任务上传")
        .navigationBarTitleDisplayMode(.inline)
        .task {
            await viewModel.loadSpots(api: ordersAPI)
        }
        .sheet(isPresented: $showCloudSelection) {
            NavigationStack {
                TaskCloudFileSelectionView { items in
                    viewModel.mergeCloudFiles(items)
                    showCloudSelection = false
                }
            }
        }
        .confirmationDialog("选择打卡点", isPresented: $showSpotPicker, titleVisibility: .visible) {
            ForEach(viewModel.spots) { spot in
                Button(spot.name.isEmpty ? "打卡点 \(spot.id)" : spot.name) {
                    viewModel.selectSpot(id: spot.id)
                }
            }
            Button("取消", role: .cancel) {}
        }
        .onChange(of: pickerItems) { items in
            Task { await importPickerItems(items) }
        }
        .alert("提示", isPresented: errorBinding) {
            Button("知道了", role: .cancel) {}
        } message: {
            Text(viewModel.errorMessage ?? "")
        }
    }

    /// 订单号和打卡点选择区域。
    private var orderSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            Text("基础信息")
                .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                .foregroundStyle(AppDesign.textPrimary)

            TextField("关联订单号", text: $viewModel.orderNumber)
                .textInputAutocapitalization(.never)
                .autocorrectionDisabled(true)
                .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)

            HStack(spacing: AppMetrics.Spacing.small) {
                Button(viewModel.isLoadingSpots ? "加载中..." : "刷新打卡点") {
                    Task { await viewModel.loadSpots(api: ordersAPI) }
                }
                .disabled(viewModel.isLoadingSpots)
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(AppDesign.primary)
                .frame(width: 104, height: 40)
                .background(AppDesign.primarySoft, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.input))

                Button {
                    showSpotPicker = true
                } label: {
                    HStack(spacing: AppMetrics.Spacing.xSmall) {
                        Text(viewModel.selectedSpotName)
                            .lineLimit(1)
                        Spacer()
                        Image(systemName: "chevron.down")
                            .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                    }
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .medium))
                    .foregroundStyle(AppDesign.textPrimary)
                    .padding(.horizontal, AppMetrics.Spacing.small)
                    .frame(maxWidth: .infinity)
                    .frame(height: 40)
                    .background(Color(hex: 0xF3F4F6), in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.input))
                }
                .buttonStyle(.plain)
                .disabled(viewModel.spots.isEmpty)
            }

            if viewModel.spots.isEmpty && !viewModel.isLoadingSpots {
                Text("暂无可选打卡点，请确认订单已完成核销。")
                    .font(.system(size: AppMetrics.FontSize.footnote))
                    .foregroundStyle(AppDesign.textSecondary)
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 云盘素材选择区域。
    private var cloudFileSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text("云盘素材")
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                Spacer()
                Button("选择云盘文件") {
                    showCloudSelection = true
                }
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(AppDesign.primary)
            }

            if viewModel.selectedCloudFiles.isEmpty {
                Text("未选择云盘文件")
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.textSecondary)
            } else {
                ForEach(viewModel.selectedCloudFiles) { file in
                    OrderTaskAttachmentRow(
                        title: file.fileName.isEmpty ? "文件 \(file.id)" : file.fileName,
                        subtitle: "云盘文件"
                    ) {
                        viewModel.removeCloudFile(id: file.id)
                    }
                }
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 本地素材选择区域。
    private var localFileSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            HStack {
                Text("本地素材")
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                Spacer()
                PhotosPicker(selection: $pickerItems, maxSelectionCount: 9, matching: .any(of: [.images, .videos])) {
                    Text("选择图片/视频")
                        .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                        .foregroundStyle(AppDesign.primary)
                }
            }

            if viewModel.selectedLocalFiles.isEmpty {
                Text("未选择本地文件")
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.textSecondary)
            } else {
                ForEach(viewModel.selectedLocalFiles) { file in
                    OrderTaskAttachmentRow(title: file.fileName, subtitle: file.statusText) {
                        viewModel.removeLocalFile(id: file.id)
                    }
                }
            }
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 提交按钮。
    private var submitButton: some View {
        Button {
            Task { await submit() }
        } label: {
            Text(viewModel.isSubmitting ? "保存中..." : "保存任务素材")
                .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                .foregroundStyle(.white)
                .frame(maxWidth: .infinity)
                .frame(height: AppMetrics.ControlSize.primaryButtonHeight)
                .background(viewModel.canSubmit ? AppDesign.primary : Color(hex: 0xC9CED6), in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.button))
        }
        .disabled(!viewModel.canSubmit)
    }

    private var errorBinding: Binding<Bool> {
        Binding(
            get: { viewModel.errorMessage != nil },
            set: { visible in
                if !visible { viewModel.clearError() }
            }
        )
    }

    /// 导入本地图片或视频。
    private func importPickerItems(_ items: [PhotosPickerItem]) async {
        for item in items {
            do {
                guard let data = try await item.loadTransferable(type: Data.self) else { continue }
                viewModel.addLocalFile(data: data, fileName: Self.fileName(for: item))
            } catch {
                toastCenter.show(error.localizedDescription)
            }
        }
        pickerItems = []
    }

    /// 提交任务素材。
    private func submit() async {
        let success = await globalLoading.withLoading {
            await viewModel.submit(api: ordersAPI, uploadService: uploadService, scenicId: accountContext.currentScenic?.id)
        }
        if success {
            toastCenter.show("任务素材已保存")
            dismiss()
        } else if let message = viewModel.errorMessage {
            toastCenter.show(message)
        }
    }

    /// 根据 PhotosPicker 类型生成本地文件名。
    private static func fileName(for item: PhotosPickerItem) -> String {
        let isVideo = item.supportedContentTypes.contains { $0.conforms(to: .movie) || $0.conforms(to: .video) }
        return "\(UUID().uuidString).\(isVideo ? "mp4" : "jpg")"
    }
}

/// 订单尾片入口页面，复用相册预览上传能力承接视频预告和尾片上传。
struct OrderTrailerView: View {
    @State private var showAlbumTrailer = false

    let orderNumber: String
    let title: String

    var body: some View {
        VStack(spacing: AppMetrics.Spacing.medium) {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                Text("订单号：\(orderNumber.isEmpty ? "--" : orderNumber)")
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.textSecondary)
                Text("用于完成订单尾片素材的最终核对与提交，按“选择相册 -> 预览文件 -> 确认上传”流程操作。")
                    .font(.system(size: AppMetrics.FontSize.footnote))
                    .foregroundStyle(AppDesign.textSecondary)
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(AppMetrics.Spacing.medium)
            .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))

            VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
                Text("提交流程")
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                trailerStep("1. 进入相册预览上传并选择目标相册")
                trailerStep("2. 核对素材内容与顺序后确认上传")
                trailerStep("3. 上传完成后返回订单页继续处理")
            }
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(AppMetrics.Spacing.medium)
            .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))

            Button("打开相册预览上传") {
                showAlbumTrailer = true
            }
            .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
            .foregroundStyle(.white)
            .frame(maxWidth: .infinity)
            .frame(height: AppMetrics.ControlSize.primaryButtonHeight)
            .background(AppDesign.primary, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.button))

            Spacer()
        }
        .padding(AppMetrics.Spacing.pageHorizontal)
        .padding(.vertical, AppMetrics.Spacing.medium)
        .background(Color(hex: 0xF5F7FA).ignoresSafeArea())
        .navigationTitle(title)
        .navigationBarTitleDisplayMode(.inline)
        .sheet(isPresented: $showAlbumTrailer) {
            NavigationStack {
                AlbumTrailerEntryView()
            }
        }
    }

    /// 构建尾片流程步骤行。
    private func trailerStep(_ text: String) -> some View {
        HStack(alignment: .top, spacing: AppMetrics.Spacing.small) {
            Circle()
                .fill(AppDesign.primary)
                .frame(width: 6, height: 6)
                .padding(.top, 6)
            Text(text)
                .font(.system(size: AppMetrics.FontSize.footnote))
                .foregroundStyle(AppDesign.textSecondary)
        }
    }
}

/// 订单任务素材附件行。
private struct OrderTaskAttachmentRow: View {
    let title: String
    let subtitle: String
    let onDelete: () -> Void

    var body: some View {
        HStack(spacing: AppMetrics.Spacing.small) {
            Image(systemName: "paperclip")
                .foregroundStyle(AppDesign.primary)
                .frame(width: AppMetrics.ControlSize.iconTapArea, height: AppMetrics.ControlSize.iconTapArea)
                .background(AppDesign.primarySoft, in: Circle())

            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxSmall) {
                Text(title)
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                    .lineLimit(1)
                Text(subtitle)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }

            Spacer()

            Button(action: onDelete) {
                Image(systemName: "xmark.circle.fill")
                    .foregroundStyle(AppDesign.placeholder)
                    .frame(width: AppMetrics.ControlSize.iconTapArea, height: AppMetrics.ControlSize.iconTapArea)
            }
            .accessibilityLabel("删除附件")
        }
        .padding(AppMetrics.Spacing.small)
        .background(Color(hex: 0xF8FAFC), in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.input))
    }
}
