//
//  AccountContext.swift
//  suixinkan
//
//  Created by Codex on 2026/6/18.
//

import Combine
import Foundation

/// 当前账号的基础资料实体，用于跨页面展示昵称、手机号和头像。
struct AccountProfile: Codable, Equatable {
    var userId: String
    var displayName: String
    var phone: String?
    var avatarURL: String?
}

/// 当前业务作用域实体，表示景区或门店维度的上下文。
struct BusinessScope: Codable, Equatable, Identifiable {
    /// 业务作用域类型，用于区分景区和门店。
    enum Kind: Codable, Equatable {
        case scenic
        case store
    }

    var id: Int
    var name: String
    var kind: Kind
    var parentScenicId: Int?
    var status: Int?
    var address: String?
    var latitude: Double?
    var longitude: Double?
    var coverURLString: String?

    /// 创建业务作用域，门店可通过 parentScenicId 标记所属景区。
    init(
        id: Int,
        name: String,
        kind: Kind,
        parentScenicId: Int? = nil,
        status: Int? = nil,
        address: String? = nil,
        latitude: Double? = nil,
        longitude: Double? = nil,
        coverURLString: String? = nil
    ) {
        self.id = id
        self.name = name
        self.kind = kind
        self.parentScenicId = parentScenicId
        self.status = status
        self.address = address
        self.latitude = latitude
        self.longitude = longitude
        self.coverURLString = coverURLString
    }
}

@MainActor
/// 账号上下文状态中心，保存当前账号资料和景区/门店作用域。
final class AccountContext: ObservableObject {
    @Published private(set) var profile: AccountProfile?
    @Published private(set) var accountType: String?
    @Published private(set) var businessUserId: Int?
    /// 当前账号在「我的」页面展示的标题，来源于登录/切换时选中的账号名称。
    @Published private(set) var currentAccountDisplayTitle: String?
    @Published private(set) var scenicScopes: [BusinessScope] = []
    @Published private(set) var storeScopes: [BusinessScope] = []
    @Published var currentScenic: BusinessScope?
    @Published var currentStore: BusinessScope?

    /// 当前账号标识，与 AccountSwitchAccount.id 规则一致。
    var currentAccountIdentifier: String? {
        guard let businessUserId, businessUserId > 0 else { return nil }
        let type = accountType?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        guard !type.isEmpty else { return nil }
        return "\(type)_\(businessUserId)"
    }

    /// 当前账号缓存前缀，与 Android 的账号级缓存作用域保持一致。
    var accountCachePrefix: String? {
        let userId = profile?.userId.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        guard !userId.isEmpty else { return nil }
        let type = accountType?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        return type.isEmpty ? userId : "\(type)_\(userId)"
    }

    /// 应用登录成功后写入账号资料。
    func applyLogin(
        profile: AccountProfile? = nil,
        accountType: String? = nil,
        businessUserId: Int? = nil,
        displayTitle: String? = nil
    ) {
        self.profile = profile
        self.accountType = accountType?.trimmingCharacters(in: .whitespacesAndNewlines)
        if let businessUserId, businessUserId > 0 {
            self.businessUserId = businessUserId
        }
        if let displayTitle = normalizedText(displayTitle) {
            currentAccountDisplayTitle = displayTitle
        }
    }

    /// 替换当前账号资料，通常用于用户信息刷新后同步全局展示。
    func replaceProfile(_ profile: AccountProfile?) {
        self.profile = profile
    }

    /// 替换景区和门店作用域，并尽量保持当前选择不变。
    func replaceScopes(
        scenic: [BusinessScope],
        stores: [BusinessScope],
        currentScenicId: Int? = nil,
        currentStoreId: Int? = nil,
        explicitSelection: Bool = false
    ) {
        scenicScopes = scenic
        storeScopes = stores

        if explicitSelection {
            currentScenic = currentScenicId.flatMap { id in
                scenic.first { $0.id == id }
            } ?? scenic.first
            if let storeId = currentStoreId, storeId > 0 {
                currentStore = resolvedStore(
                    in: stores,
                    currentScenic: currentScenic,
                    preferredStoreId: storeId,
                    allowFallbackToFirst: false
                )
            } else {
                currentStore = nil
            }
            return
        }

        currentScenic = currentScenicId.flatMap { id in
            scenic.first { $0.id == id }
        } ?? currentScenic.flatMap { current in
            scenic.first { $0.id == current.id }
        } ?? scenic.first
        currentStore = resolvedStore(
            in: stores,
            currentScenic: currentScenic,
            preferredStoreId: currentStoreId ?? currentStore?.id,
            allowFallbackToFirst: true
        )
    }

    /// 切换当前景区，并按景区重新校准当前门店。
    func selectScenic(id scenicId: Int) {
        guard let scenic = scenicScopes.first(where: { $0.id == scenicId }) else { return }
        currentScenic = scenic
        currentStore = resolvedStore(
            in: storeScopes,
            currentScenic: scenic,
            preferredStoreId: currentStore?.id,
            allowFallbackToFirst: true
        )
    }

    /// 切换当前门店，并在门店有关联景区时同步当前景区。
    func selectStore(id storeId: Int) {
        guard let store = storeScopes.first(where: { $0.id == storeId }) else { return }
        currentStore = store
        if let scenicId = store.parentScenicId,
           currentScenic?.id != scenicId,
           let scenic = scenicScopes.first(where: { $0.id == scenicId }) {
            currentScenic = scenic
        }
    }

    /// 清空账号上下文，通常在退出登录时调用。
    func reset() {
        profile = nil
        accountType = nil
        businessUserId = nil
        currentAccountDisplayTitle = nil
        scenicScopes = []
        storeScopes = []
        currentScenic = nil
        currentStore = nil
    }

    /// 按当前景区和期望门店 ID 选择有效门店。
    private func resolvedStore(
        in stores: [BusinessScope],
        currentScenic: BusinessScope?,
        preferredStoreId: Int?,
        allowFallbackToFirst: Bool
    ) -> BusinessScope? {
        let scenicId = currentScenic?.id
        let storesForScenic = stores.filter { store in
            guard let scenicId else { return true }
            return store.parentScenicId == nil || store.parentScenicId == scenicId
        }
        if let preferredStoreId,
           let store = storesForScenic.first(where: { $0.id == preferredStoreId }) {
            return store
        }
        guard allowFallbackToFirst else { return nil }
        return storesForScenic.first
    }

    /// 返回去空白后的非空文本。
    private func normalizedText(_ value: String?) -> String? {
        let text = value?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
        return text.isEmpty ? nil : text
    }
}
