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

import Foundation
import Combine

/// 云盘文件类型筛选实体，表示发布任务选择附件时的过滤方式。
enum TaskCloudFileFilter: Int, CaseIterable, Identifiable {
    case all = 0
    case video = 1
    case image = 2

    var id: Int { rawValue }

    /// 返回筛选项展示文案。
    var title: String {
        switch self {
        case .all:
            "全部"
        case .video:
            "视频"
        case .image:
            "图片"
        }
    }
}

/// 云盘文件选择 ViewModel，负责目录浏览、筛选、分页和附件选择。
@MainActor
final class TaskCloudFileSelectionViewModel: ObservableObject {
    @Published var path: [CloudDriveFile] = [CloudDriveFile(id: 0, name: "云盘")]
    @Published var files: [CloudDriveFile] = []
    @Published var total = 0
    @Published var page = 1
    @Published var searchText = ""
    @Published var selectedFilter: TaskCloudFileFilter = .all
    @Published var selectedFiles: [CloudDriveFile] = []
    private var isLoading = false
    @Published var isLoadingMore = false
    @Published var errorMessage: String?

    private let pageSize = 20

    /// 当前目录 ID。
    var currentFolderId: Int {
        path.last?.id ?? 0
    }

    /// 判断当前目录是否还有下一页。
    var hasMore: Bool {
        files.count < total
    }

    /// 重新加载当前目录第一页。
    func reload(api: any TaskServing) async throws {
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }

        do {
            let payload = try await requestFiles(api: api, page: 1)
            page = 1
            files = payload.list
            total = payload.total
        } catch {
            files = []
            total = 0
            page = 1
            errorMessage = error.localizedDescription
            throw error
        }
    }

    /// 加载当前目录下一页。
    func loadMore(api: any TaskServing) async throws {
        guard hasMore, !isLoadingMore else { return }
        isLoadingMore = true
        defer { isLoadingMore = false }

        let nextPage = page + 1
        let payload = try await requestFiles(api: api, page: nextPage)
        page = nextPage
        total = payload.total
        files.append(contentsOf: payload.list)
    }

    /// 进入指定文件夹并刷新列表。
    func enterFolder(_ folder: CloudDriveFile, api: any TaskServing) async throws {
        guard folder.isFolder else { return }
        path.append(folder)
        try await reload(api: api)
    }

    /// 回到指定面包屑目录并刷新列表。
    func popToFolder(at index: Int, api: any TaskServing) async throws {
        guard path.indices.contains(index) else { return }
        path = Array(path.prefix(index + 1))
        try await reload(api: api)
    }

    /// 切换文件选中状态，文件夹不会被选为附件。
    func toggleSelection(_ file: CloudDriveFile) {
        guard !file.isFolder else { return }
        if let index = selectedFiles.firstIndex(where: { $0.id == file.id }) {
            selectedFiles.remove(at: index)
        } else {
            selectedFiles.append(file)
        }
    }

    /// 判断指定云盘文件是否已选中。
    func isSelected(_ file: CloudDriveFile) -> Bool {
        selectedFiles.contains { $0.id == file.id }
    }

    /// 将当前选中的云盘文件转换为发布任务表单附件。
    func makeSelectionItems() -> [TaskCloudSelectionItem] {
        selectedFiles.map {
            TaskCloudSelectionItem(id: $0.id, fileName: $0.name, fileType: $0.type, remark: "")
        }
    }

    /// 组装并发送云盘文件列表请求。
    private func requestFiles(api: any TaskServing, page: Int) async throws -> ListPayload<CloudDriveFile> {
        try await api.cloudFileList(
            parentFolderId: currentFolderId,
            name: searchText.trimmingCharacters(in: .whitespacesAndNewlines),
            type: selectedFilter.rawValue,
            orderBy: 2,
            page: page,
            pageSize: pageSize
        )
    }
}
