// ── ByteLystPlatform ────────────────────────────────────────
// Unified entry point for the ByteLyst platform SDK.
// Creates and wires all platform services from a single config.
//
// Usage:
//   let platform = ByteLystPlatform(config: .init(
//       productId: "peakpulse",
//       baseURL: "https://api.peakpulse.app",
//       bundleId: "com.saravana.peakpulse"
//   ))
//
//   platform.start()                          // Start telemetry + flags + kill switch
//   platform.telemetry.trackScreen("home")    // Track events
//   let isNew = platform.flags.isEnabled("new_feature")
//   platform.stop()                           // Flush + stop timers

import Foundation

/// Unified entry point that wires all ByteLyst platform services together.
/// Create one instance at app launch and access services via properties.
public final class ByteLystPlatform {

    /// Platform configuration.
    public let config: BLPlatformConfig

    /// HTTP client shared by all services.
    public let client: BLPlatformClient

    /// Telemetry event tracking.
    public let telemetry: BLTelemetryClient

    /// Feature flag polling.
    public let flags: BLFeatureFlagClient

    /// Kill switch checker.
    public let killSwitch: BLKillSwitchClient

    /// Crash reporter (MetricKit). Created lazily on MainActor.
    public private(set) var crashReporter: BLCrashReporter?

    /// Keychain access (via bundleId as service).
    public let keychain: BLKeychainAccessor

    /// Audit logger type (static API — call BLAuditLogger.log()).
    public let auditLog: BLAuditLogger.Type = BLAuditLogger.self

    /// Auth client.
    public let auth: BLAuthClient

    /// Whether `start()` has been called.
    public private(set) var isStarted = false

    public init(config: BLPlatformConfig) {
        self.config = config
        self.client = BLPlatformClient(config: config)
        self.telemetry = BLTelemetryClient(config: config, client: client)
        self.flags = BLFeatureFlagClient(config: config, client: client)
        self.killSwitch = BLKillSwitchClient(config: config)
        self.keychain = BLKeychainAccessor(service: config.bundleId)
        self.auth = BLAuthClient(config: config, client: client)
        BLAuditLogger.configure(fileName: "\(config.productId)_audit_log.json")
    }

    /// Test-only initializer that accepts a custom URLSessionConfiguration.
    public init(config: BLPlatformConfig, sessionConfiguration: URLSessionConfiguration) {
        self.config = config
        self.client = BLPlatformClient(config: config, sessionConfiguration: sessionConfiguration)
        self.telemetry = BLTelemetryClient(config: config, client: client)
        self.flags = BLFeatureFlagClient(config: config, client: client)
        self.killSwitch = BLKillSwitchClient(config: config)
        self.keychain = BLKeychainAccessor(service: config.bundleId)
        self.auth = BLAuthClient(config: config, client: client)
        BLAuditLogger.configure(fileName: "\(config.productId)_audit_log.json")
    }

    // MARK: - Lifecycle

    /// Start all services: telemetry flush timer, feature flag polling, kill switch check.
    public func start(userId: String? = nil) {
        guard !isStarted else { return }
        isStarted = true
        telemetry.start()
        flags.start(userId: userId)
        Task { await killSwitch.check() }
        Task { @MainActor in
            self.crashReporter = BLCrashReporter(productId: config.productId)
        }
    }

    /// Stop all services: flush telemetry, stop flag polling.
    public func stop() {
        guard isStarted else { return }
        isStarted = false
        telemetry.stop()
        flags.stop()
    }
}

// MARK: - Keychain Accessor

/// Convenience wrapper around BLKeychain that binds to a specific service (bundleId).
public struct BLKeychainAccessor {
    private let service: String

    public init(service: String) {
        self.service = service
    }

    @discardableResult
    public func save(key: String, value: String) -> Bool {
        BLKeychain.save(service: service, key: key, value: value)
    }

    public func read(key: String) -> String? {
        BLKeychain.read(service: service, key: key)
    }

    @discardableResult
    public func delete(key: String) -> Bool {
        BLKeychain.delete(service: service, key: key)
    }
}
