import Foundation

/// Holds session state for an authenticated MCMS connection.
///
/// Cookie handling: `URLSession` stores the `sessionid` and `csrftoken` cookies
/// automatically and replays them. Our job is to (a) read the CSRF cookie value
/// so we can echo it in the `X-CSRFToken` header on writes (Django-style), and
/// (b) clear cookies on logout.
@MainActor
final class SessionStore {

    private(set) var isAuthenticated = false

    /// The cookie storage backing the session. Injected so a proxy deployment
    /// can use an isolated storage if needed.
    let cookieStorage: HTTPCookieStorage
    private let config: APIConfiguration

    init(config: APIConfiguration, cookieStorage: HTTPCookieStorage = .shared) {
        self.config = config
        self.cookieStorage = cookieStorage
    }

    func markAuthenticated() { isAuthenticated = true }

    /// Current CSRF token (the value of the CSRF cookie), to be sent as the
    /// `X-CSRFToken` header on mutating requests. Returns nil before login.
    func csrfToken() -> String? {
        guard let cookies = cookieStorage.cookies(for: config.baseURL) else { return nil }
        return cookies.first { Self.matches($0.name, config.csrfCookieName) }?.value
    }

    /// Whether a session cookie is currently present.
    var hasSessionCookie: Bool {
        guard let cookies = cookieStorage.cookies(for: config.baseURL) else { return false }
        return cookies.contains { Self.matches($0.name, config.sessionCookieName) }
    }

    /// Modern MCMS 6.2 builds emit `__Host-csrftoken` / `__Host-sessionid`;
    /// older ones use the bare names. Accept either form (also `__Secure-`).
    static func matches(_ cookieName: String, _ base: String) -> Bool {
        cookieName == base
            || cookieName == "__Host-" + base
            || cookieName == "__Secure-" + base
    }

    /// Drop all cookies for the configured host (call after logout / on reset).
    func clear() {
        if let cookies = cookieStorage.cookies(for: config.baseURL) {
            cookies.forEach { cookieStorage.deleteCookie($0) }
        }
        isAuthenticated = false
    }
}
