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

import AVKit
import PhotosUI
import SwiftUI
import UniformTypeIdentifiers

/// 相册管理页面，展示相册列表、筛选和新建相册入口。
struct AlbumListView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.assetsAPI) private var assetsAPI
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel = AlbumListViewModel()
    @State private var showCreateSheet = false
    @State private var newAlbumName = ""
    @State private var newAlbumRemark = ""

    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)
        .toolbar {
            ToolbarItemGroup(placement: .topBarTrailing) {
                NavigationLink {
                    AlbumTrailerEntryView()
                } label: {
                    Image(systemName: "square.and.arrow.up")
                }
                .accessibilityLabel("相册预览上传")

                Button {
                    newAlbumName = ""
                    newAlbumRemark = ""
                    showCreateSheet = true
                } label: {
                    Image(systemName: "folder.badge.plus")
                }
                .accessibilityLabel("新建相册")
            }
        }
        .refreshable { await reload(showLoading: false) }
        .task(id: accountContext.currentScenic?.id) {
            await reload(showLoading: viewModel.folders.isEmpty)
        }
        .sheet(isPresented: $showCreateSheet) {
            AlbumCreateFolderSheet(name: $newAlbumName, remark: $newAlbumRemark) {
                Task { await createAlbum() }
            }
            .presentationDetents([.medium])
        }
    }

    /// 筛选区域，包含搜索和日期输入。
    private var filterSection: some View {
        VStack(spacing: AppMetrics.Spacing.small) {
            HStack(spacing: AppMetrics.Spacing.small) {
                Image(systemName: "magnifyingglass")
                    .foregroundStyle(AppDesign.placeholder)
                TextField("搜索相册名称", text: $viewModel.searchText)
                    .submitLabel(.search)
                    .onSubmit { Task { await reload(showLoading: true) } }
                Button("搜索") {
                    Task { await reload(showLoading: true) }
                }
                .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                .foregroundStyle(AppDesign.primary)
            }
            .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)

            HStack(spacing: AppMetrics.Spacing.small) {
                TextField("开始日期 yyyy-MM-dd", text: $viewModel.startTime)
                    .textInputAutocapitalization(.never)
                    .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)
                TextField("结束日期 yyyy-MM-dd", text: $viewModel.endTime)
                    .textInputAutocapitalization(.never)
                    .appInputFieldStyle(cornerRadius: AppMetrics.CornerRadius.input, minHeight: AppMetrics.ControlSize.inputHeight)
            }

            Button {
                Task { await reload(showLoading: true) }
            } label: {
                Label("应用筛选", systemImage: "line.3.horizontal.decrease.circle")
                    .frame(maxWidth: .infinity)
            }
            .buttonStyle(.bordered)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 相册列表内容区域。
    @ViewBuilder
    private var contentSection: some View {
        if viewModel.folders.isEmpty {
            AssetsEmptyState(title: "暂无相册", message: viewModel.errorMessage ?? "当前景区还没有相册。")
        } else {
            ForEach(viewModel.folders) { folder in
                NavigationLink {
                    AlbumDetailView(folderId: folder.id, summary: folder)
                } label: {
                    AlbumFolderRow(folder: folder)
                }
                .buttonStyle(.plain)
                .onAppear {
                    guard folder.id == viewModel.folders.last?.id else { return }
                    Task { await viewModel.loadMore(api: assetsAPI, scenicId: accountContext.currentScenic?.id) }
                }
            }

            if viewModel.isLoadingMore {
                ProgressView()
                    .padding(.vertical, AppMetrics.Spacing.small)
            }
        }
    }

    /// 重新加载相册列表。
    private func reload(showLoading: Bool) async {
        await globalLoading.withOptionalLoading(showLoading && accountContext.currentScenic?.id != nil) {
            await viewModel.reload(api: assetsAPI, scenicId: accountContext.currentScenic?.id)
        }
        if let message = viewModel.errorMessage {
            toastCenter.show(message)
        }
    }

    /// 创建相册。
    private func createAlbum() async {
        let success = await globalLoading.withLoading {
            await viewModel.createFolder(
                name: newAlbumName,
                remark: newAlbumRemark,
                scenicId: accountContext.currentScenic?.id,
                api: assetsAPI
            )
        }
        toastCenter.show(success ? "相册已创建" : (viewModel.errorMessage ?? "创建失败"))
        if success {
            showCreateSheet = false
        }
    }
}

/// 相册详情页面，展示图片/视频列表并支持封面、删除和编辑。
struct AlbumDetailView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.assetsAPI) private var assetsAPI
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel: AlbumDetailViewModel
    @State private var actionFile: AlbumFileItem?
    @State private var previewFile: AlbumFileItem?
    @State private var showRenameSheet = false
    @State private var showRemarkSheet = false
    @State private var showUploadSheet = false
    @State private var renameText = ""
    @State private var remarkText = ""

    /// 初始化相册详情页面。
    init(folderId: Int, summary: AlbumFolderItem? = nil) {
        _viewModel = StateObject(wrappedValue: AlbumDetailViewModel(folderId: folderId, summary: summary))
    }

    var body: some View {
        ScrollView {
            LazyVStack(spacing: AppMetrics.Spacing.medium) {
                headerSection
                tabSection
                filesSection
            }
            .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.medium)
        }
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle(viewModel.folder?.name ?? "相册详情")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItemGroup(placement: .topBarTrailing) {
                Button {
                    showUploadSheet = true
                } label: {
                    Image(systemName: "square.and.arrow.up")
                }
                .accessibilityLabel("上传预览")

                Menu {
                    Button("编辑名称") {
                        renameText = viewModel.folder?.name ?? ""
                        showRenameSheet = true
                    }
                    Button("编辑备注") {
                        remarkText = viewModel.folder?.remark ?? ""
                        showRemarkSheet = true
                    }
                } label: {
                    Image(systemName: "ellipsis.circle")
                }
            }
        }
        .refreshable { await reload(showLoading: false) }
        .task(id: accountContext.currentScenic?.id) {
            await reload(showLoading: viewModel.files.isEmpty)
        }
        .confirmationDialog("文件操作", isPresented: actionDialogBinding, presenting: actionFile) { file in
            Button("预览") { previewFile = file }
            Button("设为封面") { Task { await setCover(file) } }
            Button("删除", role: .destructive) { Task { await delete(file) } }
        }
        .sheet(item: $previewFile) { file in
            AlbumPreviewView(file: file)
        }
        .sheet(isPresented: $showUploadSheet) {
            AlbumTrailerUploadView(initialFolderId: viewModel.folderId) {
                Task { await reload(showLoading: false) }
            }
        }
        .alert("编辑相册名称", isPresented: $showRenameSheet) {
            TextField("相册名称", text: $renameText)
            Button("取消", role: .cancel) {}
            Button("保存") { Task { await rename() } }
        }
        .alert("编辑相册备注", isPresented: $showRemarkSheet) {
            TextField("备注", text: $remarkText)
            Button("取消", role: .cancel) {}
            Button("保存") { Task { await updateRemark() } }
        }
    }

    /// 相册头部信息。
    private var headerSection: some View {
        HStack(spacing: AppMetrics.Spacing.medium) {
            RemoteImage(urlString: viewModel.folder?.coverURLString ?? "", contentMode: .fill) {
                Image(systemName: "photo.on.rectangle")
                    .font(.system(size: 32, weight: .semibold))
                    .foregroundStyle(AppDesign.primary)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(AppDesign.primarySoft)
            }
            .frame(width: 92, height: 92)
            .clipShape(RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))

            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
                Text(viewModel.folder?.name ?? "相册")
                    .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                    .lineLimit(2)
                Text("图片 \(viewModel.folder?.countImage ?? 0) · 视频 \(viewModel.folder?.countVideo ?? 0)")
                    .font(.system(size: AppMetrics.FontSize.subheadline))
                    .foregroundStyle(AppDesign.textSecondary)
                Text(viewModel.folder?.remark.assetsDisplayText ?? "暂无备注")
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
                    .lineLimit(2)
            }
            Spacer()
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 图片/视频分段切换。
    private var tabSection: some View {
        Picker("文件类型", selection: $viewModel.selectedTab) {
            ForEach(AlbumFileTab.allCases) { tab in
                Text(tab.title).tag(tab)
            }
        }
        .pickerStyle(.segmented)
        .onChange(of: viewModel.selectedTab) { tab in
            Task { await viewModel.selectTab(tab, api: assetsAPI, scenicId: accountContext.currentScenic?.id) }
        }
    }

    /// 文件网格内容区域。
    @ViewBuilder
    private var filesSection: some View {
        if viewModel.files.isEmpty {
            AssetsEmptyState(title: "暂无\(viewModel.selectedTab.title)", message: viewModel.errorMessage ?? "这个相册还没有\(viewModel.selectedTab.title)文件。")
        } else {
            LazyVGrid(columns: [GridItem(.adaptive(minimum: 150), spacing: AppMetrics.Spacing.medium)], spacing: AppMetrics.Spacing.medium) {
                ForEach(viewModel.files) { file in
                    AlbumFileCard(file: file) {
                        previewFile = file
                    } moreAction: {
                        actionFile = file
                    }
                    .onAppear {
                        guard file.id == viewModel.files.last?.id else { return }
                        Task { await viewModel.loadMore(api: assetsAPI, scenicId: accountContext.currentScenic?.id) }
                    }
                }
            }

            if viewModel.isLoadingMore {
                ProgressView()
                    .padding(.vertical, AppMetrics.Spacing.small)
            }
        }
    }

    /// 文件操作弹窗绑定。
    private var actionDialogBinding: Binding<Bool> {
        Binding(
            get: { actionFile != nil },
            set: { isPresented in
                if !isPresented { actionFile = nil }
            }
        )
    }

    /// 重新加载相册详情。
    private func reload(showLoading: Bool) async {
        await globalLoading.withOptionalLoading(showLoading && accountContext.currentScenic?.id != nil) {
            await viewModel.reload(api: assetsAPI, scenicId: accountContext.currentScenic?.id)
        }
        if let message = viewModel.errorMessage {
            toastCenter.show(message)
        }
    }

    /// 设置文件为相册封面。
    private func setCover(_ file: AlbumFileItem) async {
        let success = await globalLoading.withLoading {
            await viewModel.setCover(file: file, scenicId: accountContext.currentScenic?.id, api: assetsAPI)
        }
        toastCenter.show(success ? "已设为封面" : (viewModel.errorMessage ?? "设置失败"))
    }

    /// 删除相册文件。
    private func delete(_ file: AlbumFileItem) async {
        let success = await globalLoading.withLoading {
            await viewModel.delete(file: file, scenicId: accountContext.currentScenic?.id, api: assetsAPI)
        }
        toastCenter.show(success ? "已删除" : (viewModel.errorMessage ?? "删除失败"))
    }

    /// 保存相册名称。
    private func rename() async {
        let success = await globalLoading.withLoading {
            await viewModel.rename(name: renameText, scenicId: accountContext.currentScenic?.id, api: assetsAPI)
        }
        toastCenter.show(success ? "已保存" : (viewModel.errorMessage ?? "保存失败"))
    }

    /// 保存相册备注。
    private func updateRemark() async {
        let success = await globalLoading.withLoading {
            await viewModel.updateRemark(remarkText, scenicId: accountContext.currentScenic?.id, api: assetsAPI)
        }
        toastCenter.show(success ? "已保存" : (viewModel.errorMessage ?? "保存失败"))
    }
}

/// 相册预览上传入口页面，用于从首页选择相册并上传文件。
struct AlbumTrailerEntryView: View {
    var body: some View {
        AlbumTrailerUploadView(initialFolderId: nil, onUploaded: nil)
            .navigationTitle("相册预览上传")
            .navigationBarTitleDisplayMode(.inline)
    }
}

/// 相册预览上传页面，负责选择相册、本地文件和提交上传。
struct AlbumTrailerUploadView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.assetsAPI) private var assetsAPI
    @Environment(\.ossUploadService) private var uploadService
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.dismiss) private var dismiss
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel = AlbumTrailerViewModel()
    @State private var selectedItems: [PhotosPickerItem] = []

    let initialFolderId: Int?
    let onUploaded: (() -> Void)?

    var body: some View {
        ScrollView {
            VStack(spacing: AppMetrics.Spacing.medium) {
                folderPickerSection
                filePickerSection
                selectedFilesSection
                submitButton
            }
            .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.medium)
        }
        .background(Color(hex: 0xF5F7FA))
        .task(id: accountContext.currentScenic?.id) {
            await viewModel.loadFolders(api: assetsAPI, scenicId: accountContext.currentScenic?.id)
            if let initialFolderId {
                viewModel.selectedFolderId = initialFolderId
            }
            if let message = viewModel.errorMessage {
                toastCenter.show(message)
            }
        }
        .onChange(of: selectedItems) { items in
            Task { await loadPickedFiles(items) }
        }
    }

    /// 相册选择区域。
    private var folderPickerSection: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.small) {
            Text("选择相册")
                .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                .foregroundStyle(AppDesign.textPrimary)

            Picker("选择相册", selection: Binding(
                get: { viewModel.selectedFolderId ?? 0 },
                set: { viewModel.selectedFolderId = $0 == 0 ? nil : $0 }
            )) {
                Text("请选择相册").tag(0)
                ForEach(viewModel.folders) { folder in
                    Text(folder.name).tag(folder.id)
                }
            }
            .pickerStyle(.menu)
            .frame(maxWidth: .infinity, alignment: .leading)
            .padding(AppMetrics.Spacing.small)
            .background(Color(hex: 0xF5F7FA), in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.input))
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 本地文件选择区域。
    private var filePickerSection: some View {
        PhotosPicker(selection: $selectedItems, maxSelectionCount: 20, matching: .any(of: [.images, .videos])) {
            Label("选择图片或视频", systemImage: "photo.badge.plus")
                .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                .frame(maxWidth: .infinity)
                .padding(.vertical, AppMetrics.Spacing.medium)
        }
        .buttonStyle(.borderedProminent)
    }

    /// 已选本地文件列表。
    @ViewBuilder
    private var selectedFilesSection: some View {
        if viewModel.localFiles.isEmpty {
            AssetsEmptyState(title: "还未选择文件", message: "可一次选择最多 20 个图片或视频上传到相册。")
        } else {
            VStack(spacing: AppMetrics.Spacing.small) {
                ForEach(viewModel.localFiles) { file in
                    HStack {
                        Image(systemName: file.fileType == 1 ? "play.rectangle.fill" : "photo.fill")
                            .foregroundStyle(AppDesign.primary)
                        Text(file.fileName)
                            .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                            .foregroundStyle(AppDesign.textPrimary)
                            .lineLimit(1)
                        Spacer()
                        Button {
                            viewModel.removeLocalFile(id: file.id)
                        } label: {
                            Image(systemName: "xmark.circle.fill")
                                .frame(width: AppMetrics.ControlSize.iconTapArea, height: AppMetrics.ControlSize.iconTapArea)
                        }
                        .foregroundStyle(AppDesign.placeholder)
                    }
                }

                if viewModel.isSubmitting {
                    ProgressView(value: Double(viewModel.uploadProgress), total: 100)
                }
            }
            .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))
                .frame(maxWidth: .infinity)
                .padding(.vertical, AppMetrics.Spacing.small)
        }
        .buttonStyle(.borderedProminent)
        .disabled(viewModel.isSubmitting)
    }

    /// 读取 PhotosPicker 选择结果。
    private func loadPickedFiles(_ items: [PhotosPickerItem]) async {
        guard !items.isEmpty else { return }
        defer { selectedItems = [] }
        let files = await AssetPickerLoader.loadAlbumFiles(from: items)
        viewModel.addLocalFiles(files)
    }

    /// 提交相册预览上传。
    private func submit() async {
        let success = await globalLoading.withLoading {
            await viewModel.submit(
                scenicId: accountContext.currentScenic?.id,
                api: assetsAPI,
                uploadService: uploadService
            )
        }
        toastCenter.show(success ? "上传完成" : (viewModel.errorMessage ?? "上传失败"))
        if success {
            onUploaded?()
            dismiss()
        }
    }
}

/// 新建相册表单弹窗。
private struct AlbumCreateFolderSheet: View {
    @Binding var name: String
    @Binding var remark: String
    let submitAction: () -> Void

    @Environment(\.dismiss) private var dismiss

    var body: some View {
        NavigationStack {
            Form {
                TextField("相册名称", text: $name)
                TextField("备注", text: $remark, axis: .vertical)
                    .lineLimit(3, reservesSpace: true)
            }
            .navigationTitle("新建相册")
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarLeading) {
                    Button("取消") { dismiss() }
                }
                ToolbarItem(placement: .topBarTrailing) {
                    Button("创建", action: submitAction)
                }
            }
        }
    }
}

/// 相册文件夹行，展示封面、名称、数量和备注。
private struct AlbumFolderRow: View {
    let folder: AlbumFolderItem

    var body: some View {
        HStack(spacing: AppMetrics.Spacing.medium) {
            RemoteImage(urlString: folder.coverURLString, contentMode: .fill) {
                Image(systemName: "photo.on.rectangle")
                    .font(.system(size: 30, weight: .semibold))
                    .foregroundStyle(AppDesign.primary)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(AppDesign.primarySoft)
            }
            .frame(width: 72, height: 72)
            .clipShape(RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.input))

            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxSmall) {
                Text(folder.name.assetsDisplayText)
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
                    .lineLimit(2)
                Text("图片 \(folder.countImage) · 视频 \(folder.countVideo)")
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
                Text(folder.remark.assetsDisplayText)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
                    .lineLimit(1)
            }
            Spacer()
            Image(systemName: "chevron.right")
                .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                .foregroundStyle(AppDesign.placeholder)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }
}

/// 相册文件卡片，展示缩略图和操作按钮。
private struct AlbumFileCard: View {
    let file: AlbumFileItem
    let openAction: () -> Void
    let moreAction: () -> Void

    var body: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
            Button(action: openAction) {
                ZStack(alignment: .center) {
                    RemoteImage(urlString: file.previewURLString, contentMode: .fill) {
                        Image(systemName: file.isVideo ? "play.rectangle.fill" : "photo")
                            .font(.system(size: 30, weight: .semibold))
                            .foregroundStyle(AppDesign.primary)
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                            .background(AppDesign.primarySoft)
                    }
                    if file.isVideo {
                        Image(systemName: "play.circle.fill")
                            .font(.system(size: 36, weight: .semibold))
                            .foregroundStyle(.white)
                            .shadow(radius: 4)
                    }
                }
                .aspectRatio(1.2, contentMode: .fit)
                .clipShape(RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.input))
            }
            .buttonStyle(.plain)

            HStack(spacing: AppMetrics.Spacing.xSmall) {
                VStack(alignment: .leading, spacing: 2) {
                    Text(file.fileName.assetsDisplayText)
                        .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                        .foregroundStyle(AppDesign.textPrimary)
                        .lineLimit(1)
                    Text(file.displayFileSize)
                        .font(.system(size: AppMetrics.FontSize.caption))
                        .foregroundStyle(AppDesign.textSecondary)
                }
                Spacer()
                Button(action: moreAction) {
                    Image(systemName: "ellipsis")
                        .frame(width: AppMetrics.ControlSize.iconTapArea, height: AppMetrics.ControlSize.iconTapArea)
                }
                .buttonStyle(.plain)
                .foregroundStyle(AppDesign.textSecondary)
            }
        }
        .padding(AppMetrics.Spacing.small)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }
}

/// 相册文件预览页，支持图片和视频。
struct AlbumPreviewView: View {
    let file: AlbumFileItem

    @Environment(\.dismiss) private var dismiss

    var body: some View {
        NavigationStack {
            Group {
                if file.isVideo, let url = URL(string: file.fileUrl) {
                    VideoPlayer(player: AVPlayer(url: url))
                } else {
                    RemoteImage(urlString: file.previewURLString, contentMode: .fit) {
                        AssetsEmptyState(title: "无法预览", message: file.fileName)
                    }
                    .padding()
                }
            }
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color.black.opacity(file.isVideo ? 1 : 0.04))
            .navigationTitle(file.fileName.assetsDisplayText)
            .navigationBarTitleDisplayMode(.inline)
            .toolbar {
                ToolbarItem(placement: .topBarTrailing) {
                    Button("关闭") { dismiss() }
                }
            }
        }
    }
}

extension AssetPickerLoader {
    /// 加载相册预览上传本地文件。
    @MainActor
    static func loadAlbumFiles(from items: [PhotosPickerItem]) async -> [AlbumLocalUploadFile] {
        var result: [AlbumLocalUploadFile] = []
        for item in items {
            guard let data = try? await item.loadTransferable(type: Data.self) else { continue }
            let isVideo = item.supportedContentTypes.contains { $0.conforms(to: .movie) }
            let ext = isVideo ? "mp4" : "jpg"
            let fileName = "album_\(UUID().uuidString).\(ext)"
            result.append(AlbumLocalUploadFile(data: data, fileName: fileName, fileType: isVideo ? 1 : 2))
        }
        return result
    }
}

private extension String {
    /// 返回非空展示文本。
    var assetsDisplayText: String {
        let text = trimmingCharacters(in: .whitespacesAndNewlines)
        return text.isEmpty ? "--" : text
    }
}
