//
//  TaskAddViewModel.swift
//  suixinkan
//

import Foundation

/// 添加任务 ViewModel，对齐 Android `TaskAddViewModel` 表单与提交逻辑。
final class TaskAddViewModel {

    private(set) var taskName = ""
    private(set) var taskDetails = ""
    private(set) var selectedOrderNumber: String?
    private(set) var urgentHour = 0
    private(set) var selectedFiles: [TaskFileItem] = []
    private(set) var isUploading = false
    private(set) var showSuccessDialog = false
    private(set) var showRemarkDialog = false
    private(set) var remarkDialogText = ""
    private(set) var remarkTargetFileID: String?

    var onStateChange: (() -> Void)?
    var onShowMessage: ((String) -> Void)?

    private let appStore: AppStore
    private var pendingRemarkFileID: String?

    init(appStore: AppStore = .shared) {
        self.appStore = appStore
    }

    /// 更新任务名称。
    func updateTaskName(_ value: String) {
        taskName = String(value.prefix(20))
        notifyStateChange()
    }

    /// 更新任务描述。
    func updateTaskDetails(_ value: String) {
        taskDetails = String(value.prefix(200))
        notifyStateChange()
    }

    /// 设置关联订单号。
    func setSelectedOrderNumber(_ orderNumber: String?) {
        let trimmed = orderNumber?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        selectedOrderNumber = trimmed.isEmpty ? nil : trimmed
        notifyStateChange()
    }

    /// 设置优先级小时数。
    func setUrgentHour(_ hour: Int) {
        urgentHour = max(0, hour)
        notifyStateChange()
    }

    /// 更新自定义优先级小时文本。
    func updateCustomUrgentHourText(_ text: String) {
        let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
        guard let hour = Int(trimmed), hour > 0 else { return }
        urgentHour = hour
        notifyStateChange()
    }

    /// 合并云盘文件，去重后追加。
    func addCloudFiles(_ files: [CloudFile]) {
        let existingIDs = Set(selectedFiles.compactMap { $0.cloudFile?.id })
        let newItems = files
            .filter { !existingIDs.contains($0.id) }
            .map {
                TaskFileItem(source: .cloud, cloudFile: $0)
            }
        guard !newItems.isEmpty else { return }
        selectedFiles.append(contentsOf: newItems)
        if newItems.count == 1 {
            pendingRemarkFileID = newItems[0].id
        }
        notifyStateChange()
    }

    /// 若云盘单选后需要自动弹备注，返回目标文件 ID 并清空 pending。
    func consumePendingRemarkFileID() -> String? {
        defer { pendingRemarkFileID = nil }
        return pendingRemarkFileID
    }

    /// 添加本地上传占位项。
    @discardableResult
    func addUploadPlaceholder(fileName: String, fileType: Int, uploadTaskId: String) -> TaskFileItem {
        let item = TaskFileItem(
            source: .upload,
            uploadFileName: fileName,
            uploadFileType: fileType,
            uploadTaskId: uploadTaskId,
            isUploading: true,
            uploadProgress: 0
        )
        selectedFiles.append(item)
        isUploading = true
        notifyStateChange()
        return item
    }

    /// 更新上传进度。
    func updateUploadProgress(uploadTaskId: String, progress: Int) {
        selectedFiles = selectedFiles.map { item in
            guard item.uploadTaskId == uploadTaskId else { return item }
            var updated = item
            updated.uploadProgress = progress
            updated.isUploading = progress < 100
            return updated
        }
        notifyStateChange()
    }

    /// 本地文件读取完成后同步真实文件名与预览图。
    func prepareUpload(uploadTaskId: String, fileName: String, localPreviewData: Data?) {
        selectedFiles = selectedFiles.map { item in
            guard item.uploadTaskId == uploadTaskId else { return item }
            var updated = item
            updated.uploadFileName = fileName
            updated.localPreviewData = localPreviewData
            return updated
        }
        notifyStateChange()
    }

    /// 上传成功后更新文件 URL。
    func markUploadSucceeded(
        uploadTaskId: String,
        fileURL: String,
        fileName: String? = nil,
        coverURL: String? = nil,
        localPreviewData: Data? = nil,
        autoRemarkWhenSingle: Bool
    ) {
        selectedFiles = selectedFiles.map { item in
            guard item.uploadTaskId == uploadTaskId else { return item }
            var updated = item
            updated.uploadFileUrl = fileURL
            if let fileName, !fileName.isEmpty {
                updated.uploadFileName = fileName
            }
            updated.uploadCoverUrl = coverURL
            if let localPreviewData {
                updated.localPreviewData = localPreviewData
            }
            updated.isUploading = false
            updated.uploadProgress = 100
            return updated
        }
        isUploading = selectedFiles.contains(where: \.isUploading)
        if autoRemarkWhenSingle, let item = selectedFiles.first(where: { $0.uploadTaskId == uploadTaskId }) {
            pendingRemarkFileID = item.id
        }
        notifyStateChange()
    }

    /// 上传失败时移除占位项。
    func markUploadFailed(uploadTaskId: String) {
        selectedFiles.removeAll { $0.uploadTaskId == uploadTaskId }
        isUploading = selectedFiles.contains(where: \.isUploading)
        notifyStateChange()
    }

    /// 删除素材。
    func removeTaskFile(id: String) {
        selectedFiles.removeAll { $0.id == id }
        isUploading = selectedFiles.contains(where: \.isUploading)
        notifyStateChange()
    }

    /// 打开备注弹窗。
    func presentRemarkDialog(for fileID: String) {
        guard let file = selectedFiles.first(where: { $0.id == fileID }) else { return }
        remarkTargetFileID = fileID
        remarkDialogText = file.remark
        showRemarkDialog = true
        notifyStateChange()
    }

    /// 更新备注弹窗文本。
    func updateRemarkDialogText(_ text: String) {
        remarkDialogText = String(text.prefix(50))
        notifyStateChange()
    }

    /// 保存备注。
    func saveRemarkDialog() {
        guard let fileID = remarkTargetFileID else { return }
        selectedFiles = selectedFiles.map { item in
            guard item.id == fileID else { return item }
            var updated = item
            updated.remark = remarkDialogText
            return updated
        }
        hideRemarkDialog()
    }

    /// 关闭备注弹窗。
    func hideRemarkDialog() {
        showRemarkDialog = false
        remarkTargetFileID = nil
        remarkDialogText = ""
        notifyStateChange()
    }

    /// 当前备注弹窗对应文件。
    var remarkTargetFile: TaskFileItem? {
        guard let fileID = remarkTargetFileID else { return nil }
        return selectedFiles.first { $0.id == fileID }
    }

    /// 校验并提交任务。
    func validateAndSubmit(api: TaskAPI) async {
        if isUploading {
            onShowMessage?("文件正在上传中，请稍后添加！")
            return
        }
        let trimmedName = taskName.trimmingCharacters(in: .whitespacesAndNewlines)
        if trimmedName.isEmpty {
            onShowMessage?("请填写任务名称！")
            return
        }
        if trimmedName.count > 20 {
            onShowMessage?("任务名称不能超过20字！")
            return
        }
        if taskDetails.count > 200 {
            onShowMessage?("备注信息不能超过200字！")
            return
        }

        let request = buildAddTaskRequest(name: trimmedName)
        do {
            try await api.createTask(request)
            showSuccessDialog = true
            notifyStateChange()
        } catch is CancellationError {
            return
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    /// 构建创建任务请求体。
    func buildAddTaskRequest(name: String? = nil) -> AddTaskRequest {
        let cloudItems = selectedFiles
            .filter { $0.source == .cloud }
            .compactMap { item -> TaskCloudFileItem? in
                guard let fileId = item.cloudFile?.id else { return nil }
                return TaskCloudFileItem(fileId: fileId, remark: item.remark)
            }
        let uploadItems = selectedFiles
            .filter { $0.source == .upload }
            .compactMap { item -> TaskUploadFileItem? in
                guard let url = item.uploadFileUrl, !url.isEmpty else { return nil }
                return TaskUploadFileItem(
                    fileUrl: url,
                    fileName: item.uploadFileName ?? "",
                    remark: item.remark
                )
            }
        return AddTaskRequest(
            scenicId: appStore.session.currentScenicId,
            name: name ?? taskName,
            orderNumber: selectedOrderNumber,
            remark: taskDetails,
            urgentHour: urgentHour,
            cloudFile: cloudItems,
            uploadFile: uploadItems
        )
    }

    /// 成功弹窗选择继续添加。
    func handleContinueAdding() {
        resetAllState()
    }

    /// 关闭成功弹窗。
    func dismissSuccessDialog() {
        showSuccessDialog = false
        notifyStateChange()
    }

    /// 重置全部表单状态。
    func resetAllState() {
        taskName = ""
        taskDetails = ""
        selectedOrderNumber = nil
        urgentHour = 0
        selectedFiles = []
        isUploading = false
        showSuccessDialog = false
        hideRemarkDialog()
        pendingRemarkFileID = nil
        notifyStateChange()
    }

    /// 已导入云盘文件 ID，供云盘页禁用重复选择。
    var importedCloudFileIDs: Set<Int> {
        Set(selectedFiles.compactMap { $0.cloudFile?.id })
    }

    private func notifyStateChange() {
        onStateChange?()
    }
}
