//
//  TaskAddViewModelTests.swift
//  suixinkanTests
//

import XCTest
@testable import suixinkan

/// 添加任务 ViewModel 测试。
@MainActor
final class TaskAddViewModelTests: XCTestCase {

    private var appStore: AppStore!
    private var defaults: UserDefaults!

    override func setUp() {
        defaults = UserDefaults(suiteName: "TaskAddViewModelTests")!
        defaults.removePersistentDomain(forName: "TaskAddViewModelTests")
        appStore = AppStore(defaults: defaults)
        appStore.session.configureTestAccount(scenicId: 10)
    }

    func testValidateRequiresTaskName() async {
        let viewModel = TaskAddViewModel(appStore: appStore)
        var message: String?
        viewModel.onShowMessage = { message = $0 }

        await viewModel.validateAndSubmit(api: TaskAPI(client: makeClient()))

        XCTAssertEqual(message, "请填写任务名称！")
    }

    func testTextInputsAreTrimmedToAndroidLimits() {
        let viewModel = TaskAddViewModel(appStore: appStore)

        viewModel.updateTaskName(String(repeating: "任", count: 25))
        viewModel.updateTaskDetails(String(repeating: "描", count: 210))
        viewModel.addCloudFiles([CloudFile(id: 1, name: "A", type: 2)])
        viewModel.presentRemarkDialog(for: viewModel.selectedFiles[0].id)
        viewModel.updateRemarkDialogText(String(repeating: "注", count: 60))

        XCTAssertEqual(viewModel.taskName.count, 20)
        XCTAssertEqual(viewModel.taskDetails.count, 200)
        XCTAssertEqual(viewModel.remarkDialogText.count, 50)
    }

    func testUploadingStateBlocksSubmitButKeepsButtonActionUseful() async {
        let viewModel = TaskAddViewModel(appStore: appStore)
        viewModel.updateTaskName("任务")
        viewModel.addUploadPlaceholder(fileName: "a.jpg", fileType: 2, uploadTaskId: "task1")
        var message: String?
        viewModel.onShowMessage = { message = $0 }

        await viewModel.validateAndSubmit(api: TaskAPI(client: makeClient()))

        XCTAssertEqual(message, "文件正在上传中，请稍后添加！")
    }

    func testClearingCustomUrgentHourKeepsConfirmedValue() {
        let viewModel = TaskAddViewModel(appStore: appStore)
        viewModel.setUrgentHour(6)

        viewModel.updateCustomUrgentHourText("")
        XCTAssertEqual(viewModel.urgentHour, 6)

        viewModel.updateCustomUrgentHourText("0")
        XCTAssertEqual(viewModel.urgentHour, 6)
    }

    func testBuildAddTaskRequestSplitsCloudAndUploadFiles() {
        let viewModel = TaskAddViewModel(appStore: appStore)
        viewModel.updateTaskName("任务A")
        viewModel.updateTaskDetails("描述")
        viewModel.setSelectedOrderNumber("NO001")
        viewModel.setUrgentHour(2)
        viewModel.addCloudFiles([CloudFile(id: 1, name: "云文件", type: 2)])
        viewModel.addUploadPlaceholder(fileName: "a.jpg", fileType: 2, uploadTaskId: "task1")
        viewModel.markUploadSucceeded(uploadTaskId: "task1", fileURL: "https://cdn/a.jpg", autoRemarkWhenSingle: false)

        let request = viewModel.buildAddTaskRequest()

        XCTAssertEqual(request.name, "任务A")
        XCTAssertEqual(request.orderNumber, "NO001")
        XCTAssertEqual(request.urgentHour, 2)
        XCTAssertEqual(request.cloudFile.count, 1)
        XCTAssertEqual(request.uploadFile.count, 1)
        XCTAssertEqual(request.uploadFile[0].fileUrl, "https://cdn/a.jpg")
    }

    func testPreparedUploadKeepsOriginalFileNameAndPreview() {
        let viewModel = TaskAddViewModel(appStore: appStore)
        let previewData = Data([1, 2, 3])
        viewModel.addUploadPlaceholder(fileName: "temporary.jpg", fileType: 2, uploadTaskId: "task1")

        viewModel.prepareUpload(uploadTaskId: "task1", fileName: "IMG_1001.HEIC", localPreviewData: previewData)
        viewModel.markUploadSucceeded(
            uploadTaskId: "task1",
            fileURL: "https://cdn/image.heic",
            fileName: "IMG_1001.HEIC",
            localPreviewData: previewData,
            autoRemarkWhenSingle: true
        )

        XCTAssertEqual(viewModel.selectedFiles[0].uploadFileName, "IMG_1001.HEIC")
        XCTAssertEqual(viewModel.selectedFiles[0].localPreviewData, previewData)
        XCTAssertEqual(viewModel.buildAddTaskRequest().uploadFile[0].fileName, "IMG_1001.HEIC")
        XCTAssertEqual(viewModel.consumePendingRemarkFileID(), viewModel.selectedFiles[0].id)
    }

    func testTaskFileSourceBadgeTextMatchesAndroidLabels() {
        let cloudItem = TaskFileItem(source: .cloud, cloudFile: CloudFile(id: 1, name: "云文件", type: 2))
        let uploadItem = TaskFileItem(source: .upload, uploadFileName: "a.jpg", uploadFileType: 2)

        XCTAssertEqual(cloudItem.sourceBadgeText, "云盘")
        XCTAssertEqual(uploadItem.sourceBadgeText, "本地")
    }

    func testAddCloudFilesDedupesAndAutoRemarkSingleFile() {
        let viewModel = TaskAddViewModel(appStore: appStore)
        viewModel.addCloudFiles([CloudFile(id: 1, name: "A", type: 2)])
        XCTAssertEqual(viewModel.selectedFiles.count, 1)
        XCTAssertEqual(viewModel.consumePendingRemarkFileID(), viewModel.selectedFiles[0].id)

        viewModel.addCloudFiles([
            CloudFile(id: 1, name: "A", type: 2),
            CloudFile(id: 2, name: "B", type: 2),
            CloudFile(id: 3, name: "C", type: 2),
        ])
        XCTAssertEqual(viewModel.selectedFiles.count, 3)
        XCTAssertNil(viewModel.consumePendingRemarkFileID())
    }

    func testResetAllStateClearsForm() {
        let viewModel = TaskAddViewModel(appStore: appStore)
        viewModel.updateTaskName("任务")
        viewModel.setSelectedOrderNumber("NO001")
        viewModel.addCloudFiles([CloudFile(id: 1, type: 2)])

        viewModel.resetAllState()

        XCTAssertEqual(viewModel.taskName, "")
        XCTAssertEqual(viewModel.taskDetails, "")
        XCTAssertNil(viewModel.selectedOrderNumber)
        XCTAssertEqual(viewModel.urgentHour, 0)
        XCTAssertTrue(viewModel.selectedFiles.isEmpty)
        XCTAssertFalse(viewModel.isUploading)
        XCTAssertFalse(viewModel.showSuccessDialog)
    }

    private func makeClient() -> APIClient {
        APIClient(environment: .testing, session: MockURLSession(responses: []))
    }
}
