//
//  TravelAlbumDetailViewModel.swift
//  suixinkan
//

import Foundation

/// 旅拍相册详情 ViewModel，负责相册信息、素材分页筛选和删除状态。
final class TravelAlbumDetailViewModel {
    enum Tab: Int, Sendable {
        case all = 0
        case purchased = 1
    }

    /// 排序方式。
    enum SortOption: Int, CaseIterable, Sendable {
        case createdAsc = 1
        case createdDesc = 2
        case fileNameAsc = 3
        case fileNameDesc = 4

        var title: String {
            switch self {
            case .createdAsc: "创建时间正序"
            case .createdDesc: "创建时间倒序"
            case .fileNameAsc: "文件名正序"
            case .fileNameDesc: "文件名倒序"
            }
        }
    }

    private(set) var album: TravelAlbum?
    private(set) var materials: [TravelAlbumMaterial] = []
    private(set) var allPhotoCount = 0
    private(set) var selectedTab: Tab = .all
    private(set) var sortOption: SortOption = .createdDesc
    private(set) var isLoading = true
    private(set) var isRefreshing = false
    private(set) var isSelectionMode = false
    private(set) var selectedMaterialIds: Set<Int> = []

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

    let albumId: Int
    private var currentPage = 1
    private var canLoadMore = false
    private var isLoadingMore = false
    private let pageSize = 30

    init(albumId: Int) {
        self.albumId = albumId
    }

    /// 重新加载详情与素材。
    func refreshAll(api: any TravelAlbumServing) async {
        guard albumId > 0 else {
            isLoading = false
            onShowMessage?("相册不存在")
            notifyStateChange()
            return
        }
        isRefreshing = true
        notifyStateChange()
        await loadAlbumInfo(api: api)
        await loadAllPhotoCount(api: api)
        await loadMaterials(reset: true, api: api)
        isRefreshing = false
        isLoading = false
        notifyStateChange()
    }

    /// 拉取相册详情。
    func loadAlbumInfo(api: any TravelAlbumServing) async {
        do {
            album = try await api.info(id: albumId)
            notifyStateChange()
        } catch is CancellationError {
            return
        } catch {
            onShowMessage?(error.localizedDescription)
        }
    }

    /// 拉取全部照片数量。
    func loadAllPhotoCount(api: any TravelAlbumServing) async {
        do {
            let response = try await api.materialList(
                userEquityTravelId: albumId,
                page: 1,
                pageSize: 1,
                orderBy: sortOption.rawValue,
                isPurchased: nil
            )
            allPhotoCount = response.total
            notifyStateChange()
        } catch is CancellationError {
            return
        } catch {
            return
        }
    }

    /// 切换素材 tab。
    func selectTab(_ tab: Tab, api: any TravelAlbumServing) async {
        guard selectedTab != tab else { return }
        selectedTab = tab
        isSelectionMode = false
        selectedMaterialIds = []
        notifyStateChange()
        await loadMaterials(reset: true, api: api)
    }

    /// 切换排序。
    func setSortOption(_ option: SortOption, api: any TravelAlbumServing) async {
        guard sortOption != option else { return }
        sortOption = option
        notifyStateChange()
        await loadMaterials(reset: true, api: api)
    }

    /// 拉取素材列表。
    func loadMaterials(reset: Bool, api: any TravelAlbumServing) async {
        guard albumId > 0 else { return }
        if reset {
            currentPage = 1
            canLoadMore = false
        } else {
            guard canLoadMore, !isLoadingMore else { return }
            isLoadingMore = true
            currentPage += 1
        }

        do {
            let response = try await api.materialList(
                userEquityTravelId: albumId,
                page: currentPage,
                pageSize: pageSize,
                orderBy: sortOption.rawValue,
                isPurchased: selectedTab == .purchased ? 1 : nil
            )
            materials = reset ? response.list : materials + response.list
            canLoadMore = materials.count < response.total
            if selectedTab == .all {
                allPhotoCount = response.total
            }
            isLoadingMore = false
            notifyStateChange()
        } catch is CancellationError {
            return
        } catch {
            if !reset && currentPage > 1 {
                currentPage -= 1
            }
            isLoadingMore = false
            onShowMessage?(error.localizedDescription)
        }
    }

    /// 根据滚动位置触发加载更多。
    func loadMoreIfNeeded(lastVisibleIndex: Int, api: any TravelAlbumServing) async {
        if lastVisibleIndex >= materials.count - 6 {
            await loadMaterials(reset: false, api: api)
        }
    }

    /// 切换选择模式。
    func toggleSelectionMode() {
        guard selectedTab == .all else { return }
        isSelectionMode.toggle()
        if !isSelectionMode {
            selectedMaterialIds = []
        }
        notifyStateChange()
    }

    /// 切换素材选中状态。
    func toggleMaterialSelection(_ material: TravelAlbumMaterial) {
        guard isSelectionMode else { return }
        guard material.status == 1 else {
            onShowMessage?("仅未购买素材可删除")
            return
        }
        if selectedMaterialIds.contains(material.id) {
            selectedMaterialIds.remove(material.id)
        } else {
            selectedMaterialIds.insert(material.id)
        }
        notifyStateChange()
    }

    /// 删除已选素材。
    func deleteSelectedMaterials(api: any TravelAlbumServing) async {
        let ids = Array(selectedMaterialIds)
        guard !ids.isEmpty else {
            onShowMessage?("请选择要删除的素材")
            return
        }
        do {
            for id in ids {
                try await api.deleteMaterial(id: id)
            }
            onShowMessage?("删除成功")
            isSelectionMode = false
            selectedMaterialIds = []
            await refreshAll(api: api)
        } catch is CancellationError {
            return
        } catch {
            onShowMessage?(error.localizedDescription.isEmpty ? "删除失败" : error.localizedDescription)
        }
    }

    /// 删除当前相册。
    func deleteAlbum(api: any TravelAlbumServing) async {
        do {
            try await api.deleteAlbum(id: albumId)
            onShowMessage?("相册已删除")
            onDeletedAlbum?(albumId)
        } catch is CancellationError {
            return
        } catch {
            onShowMessage?(error.localizedDescription.isEmpty ? "删除失败" : error.localizedDescription)
        }
    }

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