//
//  SessionBootstrapper.swift
//  suixinkan
//
//  Created by Codex on 2026/6/20.
//

import Foundation
import Observation

@MainActor
@Observable
/// 登录态启动恢复器，负责冷启动时从缓存恢复并校验 token。
final class SessionBootstrapper {
    @ObservationIgnored private let tokenStore: SessionTokenStore
    @ObservationIgnored private let snapshotStore: AccountSnapshotStore
    private var didAttemptRestore = false

    /// 初始化启动恢复器，并注入 token 与账号快照存储。
    init(
        tokenStore: SessionTokenStore,
        snapshotStore: AccountSnapshotStore
    ) {
        self.tokenStore = tokenStore
        self.snapshotStore = snapshotStore
    }

    /// 创建使用默认存储服务的启动恢复器。
    convenience init() {
        self.init(
            tokenStore: SessionTokenStore(),
            snapshotStore: AccountSnapshotStore()
        )
    }

    /// 从本地缓存恢复登录态并请求服务端校验。
    func restore(
        appSession: AppSession,
        accountContext: AccountContext,
        permissionContext: PermissionContext,
        profileAPI: UserProfileServing,
        accountContextAPI: AccountContextServing,
        toastCenter: ToastCenter
    ) async {
        guard !didAttemptRestore, !appSession.isLoggedIn else { return }
        didAttemptRestore = true

        guard let token = tokenStore.load() else {
            appSession.logout()
            return
        }

        appSession.beginRestoring(token: token)
        let cachedSnapshot = restoreCachedSnapshot(to: accountContext)

        do {
            try await AccountContextLoader().refresh(
                accountContext: accountContext,
                permissionContext: permissionContext,
                profileAPI: profileAPI,
                accountContextAPI: accountContextAPI,
                cachedCurrentRoleId: cachedSnapshot?.currentRoleId,
                cachedCurrentScenicId: cachedSnapshot?.currentScenicId,
                cachedCurrentStoreId: cachedSnapshot?.currentStoreId
            )
            saveLatestSnapshot(from: accountContext, permissionContext: permissionContext)
            appSession.markLoggedIn(token: token)
        } catch {
            if APIError.isAuthenticationExpired(error) {
                try? tokenStore.clear()
                snapshotStore.clear()
                accountContext.reset()
                permissionContext.reset()
                appSession.logout()
                toastCenter.show("登录状态已失效，请重新登录")
            } else {
                appSession.markLoggedIn(token: token)
                toastCenter.show("网络异常，已使用本地登录状态")
            }
        }
    }

    /// 将缓存快照恢复到账号上下文。
    private func restoreCachedSnapshot(to accountContext: AccountContext) -> AccountSnapshot? {
        guard let snapshot = snapshotStore.load() else { return nil }
        accountContext.applyLogin(profile: snapshot.profile)
        accountContext.replaceScopes(
            scenic: snapshot.scenicScopes,
            stores: snapshot.storeScopes,
            currentScenicId: snapshot.currentScenicId,
            currentStoreId: snapshot.currentStoreId
        )
        return snapshot
    }

    /// 保存服务端校验后的最新账号上下文。
    private func saveLatestSnapshot(from accountContext: AccountContext, permissionContext: PermissionContext) {
        let existing = snapshotStore.load()
        snapshotStore.save(
            AccountSnapshot(
                profile: accountContext.profile,
                accountType: existing?.accountType,
                businessUserId: existing?.businessUserId,
                currentRoleId: permissionContext.currentRole?.id ?? existing?.currentRoleId,
                scenicScopes: accountContext.scenicScopes,
                storeScopes: accountContext.storeScopes,
                currentScenicId: accountContext.currentScenic?.id,
                currentStoreId: accountContext.currentStore?.id
            )
        )
    }

}
