// AppState.swift — global app state, credential lifecycle

import Combine
import SwiftUI

@MainActor
final class AppState: ObservableObject {
    static let shared = AppState()

    @Published var credential: SidecarCredential? = nil
    @Published var isLocked = false
    @Published var lastForegroundedAt: Date = Date()

    // T-2.10: background/foreground lifecycle publisher
    // true  = app entered background
    // false = app returned to foreground
    private let _lifecycleTransitions = PassthroughSubject<Bool, Never>()
    var lifecycleTransitions: AnyPublisher<Bool, Never> {
        _lifecycleTransitions.eraseToAnyPublisher()
    }

    private init() {
#if DEBUG
        // Test-only launch-argument overrides (gated: never active in Release).
        let args = ProcessInfo.processInfo.arguments
        if args.contains("--reset-state") {
            Keychain.shared.delete(key: "piremote.credential")
            UserDefaults.standard.removeObject(forKey: "faceid.enabled")
        }
        if args.contains("--enable-faceid") {
            UserDefaults.standard.set(true, forKey: "faceid.enabled")
        }
        if args.contains("--force-lock") {
            isLocked = true
        }
#endif

        // Try loading persisted credential on launch
        credential = try? Keychain.shared.load(key: "piremote.credential")

#if DEBUG
        // T-2.10: inject stub credential for UI tests that need MainTerminalView
        if args.contains("--uitest-with-stub-connection") {
            credential = SidecarCredential(
                sidecarId: "stub",
                host: "127.0.0.1",
                port: 19991,
                bearerToken: "stub-token",
                tlsFingerprint: "stub",
                sidecarName: "stub",
                pairedAt: Date()
            )
        }
#endif
    }

    func didPair(credential: SidecarCredential) {
        self.credential = credential
        try? Keychain.shared.save(credential, key: "piremote.credential")
    }

    func unpair() {
        credential = nil
        Keychain.shared.delete(key: "piremote.credential")
    }

    // MARK: - Face ID gate

    func appDidBackground() {
        lastForegroundedAt = Date()
        _lifecycleTransitions.send(true)  // T-2.10
    }

    func appWillForeground() async {
        _lifecycleTransitions.send(false)  // T-2.10: emit before Face-ID gate
        let elapsed = Date().timeIntervalSince(lastForegroundedAt)
        guard elapsed > 60 else { return }  // within 60s → no re-auth
        isLocked = true
        let ok = await FaceIDGate.authenticate()
        isLocked = !ok
        // N-2: after successful Face-ID auth the first emission fired when
        // isLocked=true (so MainTerminalView skipped the reconnect). Re-emit
        // now that isLocked=false so the connection actually resumes.
        if ok { _lifecycleTransitions.send(false) }
    }
}
