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

import Foundation
import Combine

/// 任务状态筛选实体，表示任务管理页支持的任务状态。
enum TaskStatusFilter: Int, CaseIterable, Identifiable {
    case all = 0
    case unaccepted = 1
    case accepted = 2
    case completed = 3
    case rejected = 4

    var id: Int { rawValue }

    /// 返回状态筛选在页面上的展示文案。
    var title: String {
        switch self {
        case .all:
            "全部"
        case .unaccepted:
            "待接收"
        case .accepted:
            "处理中"
        case .completed:
            "已完成"
        case .rejected:
            "已驳回"
        }
    }
}

/// 任务管理 ViewModel，负责任务列表、筛选、分页和错误状态。
@MainActor
final class TaskManagementViewModel: ObservableObject {
    private var isLoading = false
    @Published var isLoadingMore = false
    @Published var tasks: [PhotographerTaskItem] = []
    @Published var total = 0
    @Published var page = 1
    @Published var selectedStatus: TaskStatusFilter = .all
    @Published var searchText = ""
    @Published var startDate: Date?
    @Published var endDate: Date?
    @Published var errorMessage: String?

    private let pageSize = 10

    /// 判断任务列表是否还有下一页。
    var hasMore: Bool {
        tasks.count < total
    }

    /// 首屏加载任务列表；无景区时清空旧数据且不请求接口。
    func reload(api: any TaskServing, scenicId: Int?) async throws {
        guard let scenicId else {
            resetList()
            errorMessage = "请先选择景区"
            return
        }

        isLoading = true
        errorMessage = nil
        defer { isLoading = false }

        do {
            let payload = try await requestList(api: api, scenicId: scenicId, page: 1)
            page = 1
            tasks = payload.list
            total = payload.total
        } catch {
            resetList()
            errorMessage = error.localizedDescription
            throw error
        }
    }

    /// 加载下一页任务列表；最后一页或正在加载时不会重复请求。
    func loadMore(api: any TaskServing, scenicId: Int?) async throws {
        guard let scenicId, hasMore, !isLoadingMore else { return }
        isLoadingMore = true
        errorMessage = nil
        defer { isLoadingMore = false }

        let nextPage = page + 1
        do {
            let payload = try await requestList(api: api, scenicId: scenicId, page: nextPage)
            page = nextPage
            total = payload.total
            tasks.append(contentsOf: payload.list)
        } catch {
            errorMessage = error.localizedDescription
            throw error
        }
    }

    /// 清空任务列表和分页状态。
    func resetList() {
        tasks = []
        total = 0
        page = 1
        isLoading = false
        isLoadingMore = false
    }

    /// 组装并发送任务列表请求。
    private func requestList(api: any TaskServing, scenicId: Int, page: Int) async throws -> ListPayload<PhotographerTaskItem> {
        try await api.taskList(
            scenicId: scenicId,
            page: page,
            pageSize: pageSize,
            taskStatus: selectedStatus.rawValue,
            taskName: trimmedSearchText,
            startTime: Self.requestDateString(from: startDate),
            endTime: Self.requestDateString(from: endDate)
        )
    }

    /// 搜索关键字去除空白后为空则不传给后端。
    private var trimmedSearchText: String? {
        let text = searchText.trimmingCharacters(in: .whitespacesAndNewlines)
        return text.isEmpty ? nil : text
    }

    /// 日期请求格式化器。
    private static let requestDateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.calendar = Calendar(identifier: .gregorian)
        formatter.locale = Locale(identifier: "en_US_POSIX")
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }()

    /// 将可选日期格式化成请求字符串。
    private static func requestDateString(from date: Date?) -> String? {
        guard let date else { return nil }
        return requestDateFormatter.string(from: date)
    }
}

/// 任务详情 ViewModel，负责详情加载和列表摘要兜底展示。
@MainActor
final class TaskDetailViewModel: ObservableObject {
    private var isLoading = false
    @Published var detail: TaskDetailResponse?
    @Published var errorMessage: String?

    /// 加载任务详情；接口失败时保留外部传入的列表摘要。
    func load(api: any TaskServing, taskId: Int) async {
        isLoading = true
        errorMessage = nil
        defer { isLoading = false }

        do {
            detail = try await api.taskDetail(id: taskId)
        } catch {
            errorMessage = error.localizedDescription
        }
    }
}
