//
//  CloudStorageViews.swift
//  suixinkan
//
//  Created by Codex on 2026/6/23.
//

import AVKit
import Foundation
import PhotosUI
import SwiftUI
import UniformTypeIdentifiers
import UIKit

/// 相册云盘页面，展示文件夹浏览、筛选、上传、预览和文件操作。
struct CloudStorageView: View {
    @EnvironmentObject private var accountContext: AccountContext
    @Environment(\.assetsAPI) private var assetsAPI
    @Environment(\.ossUploadService) private var uploadService
    @EnvironmentObject private var router: RouterPath
    @EnvironmentObject private var toastCenter: ToastCenter
    @Environment(\.globalLoading) private var globalLoading

    @StateObject private var viewModel = CloudStorageViewModel()
    @State private var transferStore = CloudTransferStore.shared
    @State private var selectedItems: [PhotosPickerItem] = []
    @State private var actionItem: CloudDriveFile?
    @State private var previewItem: CloudDriveFile?
    @State private var isCreatingFolder = false
    @State private var folderName = ""
    @State private var isRenaming = false
    @State private var renamingItem: CloudDriveFile?
    @State private var renameText = ""
    @State private var movingItem: CloudDriveFile?

    var body: some View {
        ScrollView {
            LazyVStack(spacing: AppMetrics.Spacing.medium) {
                toolbarSection
                breadcrumbSection
                filterSection
                contentSection
            }
            .padding(.horizontal, AppMetrics.Spacing.pageHorizontal)
            .padding(.vertical, AppMetrics.Spacing.medium)
        }
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle("相册云盘")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItemGroup(placement: .topBarTrailing) {
                Button {
                    router.navigate(to: .home(.cloudStorageTransit))
                } label: {
                    Image(systemName: "arrow.up.arrow.down")
                }
                .accessibilityLabel("传输记录")

                Button {
                    folderName = ""
                    isCreatingFolder = true
                } label: {
                    Image(systemName: "folder.badge.plus")
                }
                .accessibilityLabel("新建文件夹")
            }
        }
        .refreshable { await reload(showLoading: false) }
        .task {
            guard viewModel.files.isEmpty else { return }
            await reload(showLoading: true)
        }
        .onChange(of: selectedItems) { items in
            Task { await upload(items) }
        }
        .confirmationDialog("文件操作", isPresented: actionDialogBinding, presenting: actionItem) { item in
            Button("预览") { previewItem = item }
            Button("下载") { Task { await download(item) } }
            Button("重命名") {
                renamingItem = item
                renameText = item.name
                isRenaming = true
            }
            Button("移动") { movingItem = item }
            Button("删除", role: .destructive) { Task { await delete(item) } }
        }
        .alert("新建文件夹", isPresented: $isCreatingFolder) {
            TextField("文件夹名称", text: $folderName)
            Button("取消", role: .cancel) {}
            Button("创建") { Task { await createFolder() } }
        }
        .alert("重命名", isPresented: $isRenaming) {
            TextField("名称", text: $renameText)
            Button("取消", role: .cancel) {}
            Button("保存") { Task { await renameSelectedItem() } }
        }
        .sheet(item: $movingItem) { item in
            CloudMoveFolderSheet(item: item, folders: moveTargets) { folderId in
                Task { await move(item, targetFolderId: folderId) }
            }
            .presentationDetents([.medium])
        }
        .sheet(item: $previewItem) { item in
            CloudFilePreviewView(item: item)
        }
    }

    /// 顶部工具区域，包含上传入口和当前统计。
    private var toolbarSection: some View {
        HStack(spacing: AppMetrics.Spacing.medium) {
            VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxSmall) {
                Text("当前目录")
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
                Text(viewModel.path.last?.name ?? "云盘")
                    .font(.system(size: AppMetrics.FontSize.title3, weight: .semibold))
                    .foregroundStyle(AppDesign.textPrimary)
            }

            Spacer()

            PhotosPicker(selection: $selectedItems, maxSelectionCount: 20, matching: .any(of: [.images, .videos])) {
                Label("上传", systemImage: "square.and.arrow.up")
                    .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
            }
            .buttonStyle(.borderedProminent)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 面包屑区域，展示当前云盘路径。
    private var breadcrumbSection: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: AppMetrics.Spacing.xSmall) {
                ForEach(Array(viewModel.path.enumerated()), id: \.element.id) { index, folder in
                    Button {
                        Task { await viewModel.popToFolder(at: index, api: assetsAPI) }
                    } label: {
                        Text(folder.name)
                            .font(.system(size: AppMetrics.FontSize.subheadline, weight: .semibold))
                    }
                    .foregroundStyle(index == viewModel.path.count - 1 ? AppDesign.primary : AppDesign.textSecondary)

                    if index < viewModel.path.count - 1 {
                        Image(systemName: "chevron.right")
                            .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                            .foregroundStyle(AppDesign.placeholder)
                    }
                }
            }
            .padding(.vertical, AppMetrics.Spacing.xSmall)
        }
    }

    /// 筛选区域，包含搜索、类型和排序。
    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)

            Picker("类型", selection: $viewModel.selectedFilter) {
                ForEach(CloudDriveFilter.allCases) { filter in
                    Text(filter.title).tag(filter)
                }
            }
            .pickerStyle(.segmented)
            .onChange(of: viewModel.selectedFilter) { _ in
                Task { await reload(showLoading: true) }
            }

            Picker("排序", selection: $viewModel.selectedSort) {
                ForEach(CloudDriveSort.allCases) { sort in
                    Text(sort.title).tag(sort)
                }
            }
            .pickerStyle(.segmented)
            .onChange(of: viewModel.selectedSort) { _ in
                Task { await reload(showLoading: true) }
            }
        }
    }

    /// 列表内容区域，展示空状态、文件行和加载更多。
    @ViewBuilder
    private var contentSection: some View {
        if viewModel.files.isEmpty {
            AssetsEmptyState(title: "暂无文件", message: viewModel.errorMessage ?? "当前目录还没有云盘文件。")
        } else {
            ForEach(viewModel.files) { item in
                CloudDriveFileRow(item: item) {
                    if item.isFolder {
                        Task { await viewModel.enterFolder(item, api: assetsAPI) }
                    } else {
                        previewItem = item
                    }
                } moreAction: {
                    actionItem = item
                }
                .onAppear {
                    guard item.id == viewModel.files.last?.id else { return }
                    Task { await viewModel.loadMore(api: assetsAPI) }
                }
            }

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

    /// 操作弹窗的绑定，关闭时同步清空当前文件。
    private var actionDialogBinding: Binding<Bool> {
        Binding(
            get: { actionItem != nil },
            set: { isPresented in
                if !isPresented { actionItem = nil }
            }
        )
    }

    /// 可移动到的目标文件夹，当前版本提供根目录和当前目录可见文件夹。
    private var moveTargets: [CloudDriveFile] {
        [CloudDriveFile(id: 0, name: "云盘")] + viewModel.files.filter(\.isFolder)
    }

    /// 重新加载当前目录。
    private func reload(showLoading: Bool) async {
        await globalLoading.withOptionalLoading(showLoading) {
            await viewModel.reload(api: assetsAPI)
        }
        if let message = viewModel.errorMessage {
            toastCenter.show(message)
        }
    }

    /// 创建文件夹。
    private func createFolder() async {
        let success = await globalLoading.withLoading {
            await viewModel.createFolder(name: folderName, api: assetsAPI)
        }
        toastCenter.show(success ? "文件夹已创建" : (viewModel.errorMessage ?? "创建失败"))
    }

    /// 重命名当前选中的文件或文件夹。
    private func renameSelectedItem() async {
        guard let item = renamingItem else { return }
        let success = await globalLoading.withLoading {
            await viewModel.rename(item, newName: renameText, api: assetsAPI)
        }
        toastCenter.show(success ? "已重命名" : (viewModel.errorMessage ?? "重命名失败"))
        renamingItem = nil
    }

    /// 删除文件或文件夹。
    private func delete(_ item: CloudDriveFile) async {
        let success = await globalLoading.withLoading {
            await viewModel.delete(item, api: assetsAPI)
        }
        toastCenter.show(success ? "已删除" : (viewModel.errorMessage ?? "删除失败"))
    }

    /// 移动文件或文件夹。
    private func move(_ item: CloudDriveFile, targetFolderId: Int) async {
        movingItem = nil
        let success = await globalLoading.withLoading {
            await viewModel.move(item, targetFolderId: targetFolderId, api: assetsAPI)
        }
        toastCenter.show(success ? "已移动" : (viewModel.errorMessage ?? "移动失败"))
    }

    /// 读取 PhotosPicker 结果并上传到云盘。
    private func upload(_ items: [PhotosPickerItem]) async {
        guard !items.isEmpty else { return }
        defer { selectedItems = [] }
        let localFiles = await AssetPickerLoader.loadCloudFiles(from: items)
        let success = await globalLoading.withLoading {
            await viewModel.upload(
                localFiles: localFiles,
                scenicId: accountContext.currentScenic?.id,
                api: assetsAPI,
                uploadService: uploadService,
                transferStore: transferStore
            )
        }
        toastCenter.show(success ? "上传完成" : (viewModel.errorMessage ?? "上传失败"))
    }

    /// 下载云盘文件到 App 沙盒 Documents/CloudDownloads。
    private func download(_ item: CloudDriveFile) async {
        guard let url = URL(string: item.fileUrl), !item.isFolder else {
            toastCenter.show("文件地址无效")
            return
        }
        let transferId = transferStore.start(fileName: item.name, direction: .download)
        do {
            let (tempURL, _) = try await URLSession.shared.download(from: url)
            let fileManager = FileManager.default
            let documents = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            let folder = documents.appendingPathComponent("CloudDownloads", isDirectory: true)
            try fileManager.createDirectory(at: folder, withIntermediateDirectories: true)
            let destination = folder.appendingPathComponent(uniqueFileName(item.name, in: folder))
            if fileManager.fileExists(atPath: destination.path) {
                try fileManager.removeItem(at: destination)
            }
            try fileManager.moveItem(at: tempURL, to: destination)
            transferStore.succeed(id: transferId, message: destination.lastPathComponent)
            toastCenter.show("已下载到 CloudDownloads")
        } catch {
            transferStore.fail(id: transferId, message: error.localizedDescription)
            toastCenter.show("下载失败")
        }
    }

    /// 生成不覆盖已有文件的下载文件名。
    private func uniqueFileName(_ name: String, in folder: URL) -> String {
        let fileManager = FileManager.default
        let base = URL(fileURLWithPath: name).deletingPathExtension().lastPathComponent.assetsNonEmpty ?? "download"
        let ext = URL(fileURLWithPath: name).pathExtension
        var candidate = name
        var index = 1
        while fileManager.fileExists(atPath: folder.appendingPathComponent(candidate).path) {
            candidate = ext.isEmpty ? "\(base)-\(index)" : "\(base)-\(index).\(ext)"
            index += 1
        }
        return candidate
    }
}

/// 云盘文件行，展示图标、名称、大小和操作按钮。
private struct CloudDriveFileRow: View {
    let item: CloudDriveFile
    let openAction: () -> Void
    let moreAction: () -> Void

    var body: some View {
        HStack(spacing: AppMetrics.Spacing.medium) {
            Button(action: openAction) {
                thumbnail
                    .frame(width: 54, height: 54)
                    .clipShape(RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.input))
            }
            .buttonStyle(.plain)

            Button(action: openAction) {
                VStack(alignment: .leading, spacing: AppMetrics.Spacing.xxSmall) {
                    Text(item.name)
                        .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                        .foregroundStyle(AppDesign.textPrimary)
                        .lineLimit(2)
                    Text(item.isFolder ? "\(item.childNum) 项" : "\(item.fileSize.formattedFileSize) · \(item.createdAt)")
                        .font(.system(size: AppMetrics.FontSize.caption))
                        .foregroundStyle(AppDesign.textSecondary)
                        .lineLimit(1)
                }
                .frame(maxWidth: .infinity, alignment: .leading)
            }
            .buttonStyle(.plain)

            Button(action: moreAction) {
                Image(systemName: "ellipsis")
                    .frame(width: AppMetrics.ControlSize.iconTapArea, height: AppMetrics.ControlSize.iconTapArea)
            }
            .buttonStyle(.plain)
            .foregroundStyle(AppDesign.textSecondary)
        }
        .padding(AppMetrics.Spacing.medium)
        .background(.white, in: RoundedRectangle(cornerRadius: AppMetrics.CornerRadius.card))
    }

    /// 云盘文件缩略图。
    @ViewBuilder
    private var thumbnail: some View {
        if item.isFolder {
            Image(systemName: "folder.fill")
                .font(.system(size: 30, weight: .semibold))
                .foregroundStyle(AppDesign.warning)
                .frame(maxWidth: .infinity, maxHeight: .infinity)
                .background(Color(hex: 0xFFF7ED))
        } else {
            RemoteImage(urlString: item.previewURLString, contentMode: .fill) {
                Image(systemName: item.isVideo ? "play.rectangle.fill" : "photo")
                    .font(.system(size: 26, weight: .semibold))
                    .foregroundStyle(AppDesign.primary)
                    .frame(maxWidth: .infinity, maxHeight: .infinity)
                    .background(AppDesign.primarySoft)
            }
        }
    }
}

/// 云盘移动目标选择弹窗。
private struct CloudMoveFolderSheet: View {
    let item: CloudDriveFile
    let folders: [CloudDriveFile]
    let selectAction: (Int) -> Void

    @Environment(\.dismiss) private var dismiss

    var body: some View {
        NavigationStack {
            List(folders.filter { $0.id != item.id }) { folder in
                Button {
                    selectAction(folder.id)
                    dismiss()
                } label: {
                    Label(folder.name, systemImage: folder.id == 0 ? "externaldrive" : "folder")
                }
            }
            .navigationTitle("移动到")
            .navigationBarTitleDisplayMode(.inline)
        }
    }
}

/// 云盘文件预览页面，支持图片和视频的安全预览。
private struct CloudFilePreviewView: View {
    let item: CloudDriveFile

    @Environment(\.dismiss) private var dismiss

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

/// 云盘传输记录页面，展示本次会话内上传和下载记录。
struct CloudStorageTransitView: View {
    @State private var transferStore = CloudTransferStore.shared

    var body: some View {
        List {
            if transferStore.records.isEmpty {
                AssetsEmptyState(title: "暂无传输记录", message: "上传和下载记录只保留在本次 App 会话内。")
                    .listRowSeparator(.hidden)
                    .listRowBackground(Color.clear)
            } else {
                ForEach(transferStore.records) { record in
                    CloudTransferRow(record: record)
                }
            }
        }
        .listStyle(.plain)
        .background(Color(hex: 0xF5F7FA))
        .navigationTitle("传输记录")
        .navigationBarTitleDisplayMode(.inline)
        .toolbar {
            ToolbarItem(placement: .topBarTrailing) {
                Button("清空") { transferStore.clear() }
                    .disabled(transferStore.records.isEmpty)
            }
        }
    }
}

/// 云盘传输记录行。
private struct CloudTransferRow: View {
    let record: CloudTransferItem

    var body: some View {
        VStack(alignment: .leading, spacing: AppMetrics.Spacing.xSmall) {
            HStack {
                Image(systemName: record.direction == .upload ? "arrow.up.circle.fill" : "arrow.down.circle.fill")
                    .foregroundStyle(record.status == .failed ? Color.red : AppDesign.primary)
                Text(record.fileName)
                    .font(.system(size: AppMetrics.FontSize.body, weight: .semibold))
                    .lineLimit(1)
                Spacer()
                Text(record.status.title)
                    .font(.system(size: AppMetrics.FontSize.caption, weight: .semibold))
                    .foregroundStyle(record.status.color)
            }
            ProgressView(value: Double(record.progress), total: 100)
            if !record.message.isEmpty {
                Text(record.message)
                    .font(.system(size: AppMetrics.FontSize.caption))
                    .foregroundStyle(AppDesign.textSecondary)
            }
        }
        .padding(.vertical, AppMetrics.Spacing.xSmall)
    }
}

/// 资产模块空状态视图。
struct AssetsEmptyState: View {
    let title: String
    let message: String

    var body: some View {
        VStack(spacing: AppMetrics.Spacing.small) {
            Image(systemName: "tray")
                .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))
    }
}

/// PhotosPicker 数据加载器，把系统选择结果转换为模块内本地文件实体。
enum AssetPickerLoader {
    /// 加载云盘本地文件。
    @MainActor
    static func loadCloudFiles(from items: [PhotosPickerItem]) async -> [CloudLocalUploadFile] {
        var result: [CloudLocalUploadFile] = []
        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 = "cloud_\(UUID().uuidString).\(ext)"
            result.append(CloudLocalUploadFile(data: data, fileName: fileName, fileType: isVideo ? 1 : 2))
        }
        return result
    }

    /// 加载素材本地文件。
    @MainActor
    static func loadMediaFiles(from items: [PhotosPickerItem]) async -> [MediaLocalUploadFile] {
        var result: [MediaLocalUploadFile] = []
        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 image = isVideo ? nil : UIImage(data: data)
            let fileName = "media_\(UUID().uuidString).\(ext)"
            result.append(
                MediaLocalUploadFile(
                    data: data,
                    fileName: fileName,
                    fileType: isVideo ? 1 : 2,
                    width: Int(image?.size.width ?? 0),
                    height: Int(image?.size.height ?? 0)
                )
            )
        }
        return result
    }
}

private extension CloudTransferStatus {
    /// 返回传输状态展示文案。
    var title: String {
        switch self {
        case .running:
            "进行中"
        case .success:
            "完成"
        case .failed:
            "失败"
        }
    }

    /// 返回传输状态展示颜色。
    var color: Color {
        switch self {
        case .running:
            AppDesign.primary
        case .success:
            AppDesign.success
        case .failed:
            .red
        }
    }
}

private extension Int64 {
    /// 返回文件大小展示文案。
    var formattedFileSize: String {
        let value = Double(self)
        if value >= 1_073_741_824 {
            return String(format: "%.1fGB", value / 1_073_741_824)
        }
        if value >= 1_048_576 {
            return String(format: "%.1fMB", value / 1_048_576)
        }
        if value >= 1024 {
            return String(format: "%.1fKB", value / 1024)
        }
        return "\(self)B"
    }
}

extension String {
    /// 返回去除空白后的非空字符串，供资产页面避免依赖其他文件私有扩展。
    var assetsNonEmpty: String? {
        let value = trimmingCharacters(in: .whitespacesAndNewlines)
        return value.isEmpty ? nil : value
    }
}
