import Foundation

/// Holds the signed-in session (JWT + userId). Cached in memory for the API client and persisted
/// to UserDefaults. Production should move the token to the Keychain and obtain it from a real
/// OTP/Keycloak login; here it's the JWT auth-service issues after OTP verification.
final class SessionStore: ObservableObject {

    struct Session: Equatable {
        let token: String
        let userId: String
    }

    @Published private(set) var session: Session?

    var token: String? { session?.token }
    var userId: String? { session?.userId }
    /// Exchanged for a new access token when the current one expires.
    private(set) var refreshToken: String?
    var isLoggedIn: Bool { session != nil }

    private let defaults = UserDefaults.standard

    init() {
        refreshToken = defaults.string(forKey: Keys.refresh)
        if let token = defaults.string(forKey: Keys.token),
           let userId = defaults.string(forKey: Keys.userId) {
            session = Session(token: token, userId: userId)
        }
    }

    func save(token: String, userId: String, refreshToken: String? = nil) {
        defaults.set(token, forKey: Keys.token)
        defaults.set(userId, forKey: Keys.userId)
        if let refreshToken {
            defaults.set(refreshToken, forKey: Keys.refresh)
            self.refreshToken = refreshToken
        }
        session = Session(token: token, userId: userId)
    }

    /// Replace the tokens after a refresh, leaving the rest of the session alone so nothing
    /// re-navigates.
    func updateTokens(access: String, refresh: String) {
        defaults.set(access, forKey: Keys.token)
        defaults.set(refresh, forKey: Keys.refresh)
        refreshToken = refresh
        if let userId = session?.userId {
            session = Session(token: access, userId: userId)
        }
    }

    func clear() {
        defaults.removeObject(forKey: Keys.token)
        defaults.removeObject(forKey: Keys.userId)
        defaults.removeObject(forKey: Keys.refresh)
        refreshToken = nil
        session = nil
    }

    private enum Keys {
        static let token = "beebbeeb.token"
        static let userId = "beebbeeb.userId"
        static let refresh = "beebbeeb.refreshToken"
    }
}
