//
//  PermissionApplyViewModel.swift
//  suixinkan
//

import Foundation

/// 权限申请 ViewModel，对齐 Android `PermissionApplyViewModel`。
final class PermissionApplyViewModel {

    private(set) var availableRoles: [RoleOption] = []
    private(set) var selectedRoleId: Int?
    private(set) var selectedRoleName = ""
    private(set) var availableScenics: [ScenicOption] = []
    private(set) var selectedScenicIds: [Int] = []
    private(set) var selectedScenicNames: [String] = []
    private(set) var isLoadingScenics = false
    private(set) var isSubmitting = false
    private(set) var showRolePicker = false
    private(set) var showScenicPicker = false
    private(set) var rolePermissionList: [RolePermissionResponse] = []
    private(set) var scenicSearchQuery = ""
    private(set) var pendingDeletion: PermissionDeletionTarget?
    private(set) var showScenicListDialog = false
    private(set) var dialogRoleName = ""
    private(set) var dialogScenicList: [ScenicInfo] = []

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

    private let appStore: AppStore

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

    /// 当前表单是否满足 Android 的提交条件。
    var canSubmit: Bool {
        selectedRoleId != nil && !selectedScenicIds.isEmpty && !isSubmitting
    }

    /// 按当前搜索词过滤景区，保持接口原始顺序。
    var filteredScenics: [ScenicOption] {
        let query = scenicSearchQuery.trimmingCharacters(in: .whitespacesAndNewlines)
        guard !query.isEmpty else { return availableScenics }
        return availableScenics.filter { $0.name.localizedCaseInsensitiveContains(query) }
    }

    /// 从待审核数据预填表单（status=3 去编辑）。
    func initWithPendingData(_ pending: RoleApplyPendingResponse) {
        selectedRoleId = pending.roleId
        selectedRoleName = pending.roleName
        selectedScenicIds = pending.scenicList.map(\.id)
        selectedScenicNames = pending.scenicList.map(\.name)
        availableRoles = availableRoles.map { role in
            var copy = role
            copy.isSelected = role.id == pending.roleId
            return copy
        }
        notifyStateChange()
    }

    func loadRolesFromLocal() {
        rolePermissionList = appStore.permissions.rolePermissionList()
        var seen = Set<Int>()
        availableRoles = rolePermissionList.compactMap { item in
            guard !seen.contains(item.role.id) else { return nil }
            seen.insert(item.role.id)
            return RoleOption(
                id: item.role.id,
                name: item.role.name,
                description: item.role.notes ?? "",
                isSelected: false
            )
        }
        notifyStateChange()
    }

    func showRolePickerSheet() {
        showRolePicker = true
        notifyStateChange()
    }

    func hideRolePickerSheet() {
        showRolePicker = false
        notifyStateChange()
    }

    func selectRole(_ role: RoleOption) {
        selectedRoleId = role.id
        selectedRoleName = role.name
        availableRoles = availableRoles.map { item in
            var copy = item
            copy.isSelected = item.id == role.id
            return copy
        }
        selectedScenicIds = []
        selectedScenicNames = []
        availableScenics = []
        showRolePicker = false
        notifyStateChange()
    }

    func showScenicPickerSheet() {
        guard selectedRoleId != nil else {
            onShowMessage?("请先选择角色")
            return
        }
        showScenicPicker = true
        notifyStateChange()
    }

    func hideScenicPickerSheet() {
        showScenicPicker = false
        notifyStateChange()
    }

    func loadAvailableScenics(api: HomeAPI?) async {
        guard let roleId = selectedRoleId else { return }
        guard let api else { return }
        guard !isLoadingScenics else { return }
        isLoadingScenics = true
        notifyStateChange()
        do {
            let response = try await api.scenicListAll()
            let existingIds = existingScenicIds(for: roleId)
            availableScenics = response.list.map { scenic in
                let isExisting = existingIds.contains(scenic.id)
                let isPreselected = selectedScenicIds.contains(scenic.id)
                return ScenicOption(
                    id: scenic.id,
                    name: scenic.name,
                    isSelected: isExisting || isPreselected,
                    isDisabled: isExisting
                )
            }
        } catch {
            onShowMessage?("获取景区列表失败")
        }
        isLoadingScenics = false
        notifyStateChange()
    }

    func toggleScenic(_ scenic: ScenicOption) {
        guard !scenic.isDisabled else { return }
        if selectedScenicIds.contains(scenic.id) {
            selectedScenicIds.removeAll { $0 == scenic.id }
            selectedScenicNames.removeAll { $0 == scenic.name }
        } else {
            selectedScenicIds.append(scenic.id)
            selectedScenicNames.append(scenic.name)
        }
        availableScenics = availableScenics.map { item in
            var copy = item
            if !copy.isDisabled {
                copy.isSelected = selectedScenicIds.contains(copy.id)
            }
            return copy
        }
        notifyStateChange()
    }

    /// 更新景区下拉菜单的搜索词。
    func updateScenicSearchQuery(_ query: String) {
        scenicSearchQuery = query
        notifyStateChange()
    }

    func removeSelectedScenic(id: Int, name: String) {
        pendingDeletion = .scenic(id: id, name: name)
        notifyStateChange()
    }

    /// 确认删除当前待删除的角色或景区。
    func confirmDeletion() {
        guard let pendingDeletion else { return }
        switch pendingDeletion {
        case .role:
            clearRoleSelectionImmediately()
        case .scenic(let id, let name):
            removeSelectedScenicImmediately(id: id, name: name)
        }
        self.pendingDeletion = nil
        notifyStateChange()
    }

    /// 取消删除确认。
    func cancelDeletion() {
        pendingDeletion = nil
        notifyStateChange()
    }

    private func removeSelectedScenicImmediately(id: Int, name: String) {
        selectedScenicIds.removeAll { $0 == id }
        selectedScenicNames.removeAll { $0 == name }
        availableScenics = availableScenics.map { item in
            var copy = item
            if !copy.isDisabled {
                copy.isSelected = selectedScenicIds.contains(copy.id)
            }
            return copy
        }
    }

    /// 已有角色下已开通的景区列表。
    func existingScenics(for roleId: Int) -> [ScenicInfo] {
        appStore.permissions.rolePermissionList()
            .filter { $0.role.id == roleId }
            .flatMap(\.scenic)
    }

    func clearRoleSelection() {
        guard !selectedRoleName.isEmpty else { return }
        pendingDeletion = .role(name: selectedRoleName)
        notifyStateChange()
    }

    private func clearRoleSelectionImmediately() {
        selectedRoleId = nil
        selectedRoleName = ""
        selectedScenicIds = []
        selectedScenicNames = []
        availableScenics = []
        availableRoles = availableRoles.map { role in
            var copy = role
            copy.isSelected = false
            return copy
        }
    }

    /// 展示已有角色下的全部景区。
    func showScenicList(roleName: String, scenics: [ScenicInfo]) {
        dialogRoleName = roleName
        dialogScenicList = scenics
        showScenicListDialog = true
        notifyStateChange()
    }

    /// 关闭已有景区列表弹窗。
    func hideScenicList() {
        dialogRoleName = ""
        dialogScenicList = []
        showScenicListDialog = false
        notifyStateChange()
    }

    func submit(api: HomeAPI) async {
        guard canSubmit, let roleId = selectedRoleId else {
            onShowMessage?("请选择景区和角色")
            return
        }

        isSubmitting = true
        notifyStateChange()
        do {
            try await api.submitRoleApply(scenicIds: selectedScenicIds, roleId: roleId)
            isSubmitting = false
            notifyStateChange()
            onSubmitSuccess?()
        } catch {
            onShowMessage?("提交失败，请稍后重试")
            isSubmitting = false
            notifyStateChange()
        }
    }

    private func existingScenicIds(for roleId: Int) -> Set<Int> {
        Set(existingScenics(for: roleId).map(\.id))
    }

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