import SwiftUI
import Combine
import OSLog

private let personalityLogger = Logger(subsystem: "nahbar", category: "PersonalityStore")

// MARK: - PersonalityStoring Protocol

/// Protokoll für Testbarkeit und Dependency Injection.
protocol PersonalityStoring: AnyObject {
    var profile: PersonalityProfile? { get }
    var hasCompletedQuiz: Bool { get }
    func save(profile: PersonalityProfile)
    func reset()
}

// MARK: - PersonalityStore

/// Speichert das OCEAN-Persönlichkeitsprofil lokal in UserDefaults.
/// Folgt dem Singleton-Muster von UserProfileStore.
/// Kein SwiftData – ein einzelnes Profil braucht kein relationales Modell.
final class PersonalityStore: ObservableObject, PersonalityStoring {

    static let shared = PersonalityStore()

    // MARK: Öffentlicher Zustand

    @Published private(set) var profile: PersonalityProfile? = nil

    var hasCompletedQuiz: Bool { profile?.isComplete == true }

    /// Gibt an, ob der Nutzer das Quiz beim Onboarding übersprungen hat.
    @AppStorage("hasSkippedPersonalityQuiz") var hasSkippedQuiz: Bool = false

    // MARK: Persistence

    private let defaults = UserDefaults.standard
    private let storageKey = "nahbar.personalityProfile"

    private init() { load() }

    // MARK: Schreiben

    func save(profile: PersonalityProfile) {
        self.profile = profile
        persist()
        personalityLogger.debug("Persönlichkeitsprofil gespeichert (completedAt: \(profile.completedAt?.description ?? "nil"))")
    }

    /// Setzt das Profil zurück (Entwickler-Werkzeug + "Erneut ausfüllen"-Flow).
    func reset() {
        defaults.removeObject(forKey: storageKey)
        profile = nil
        hasSkippedQuiz = false
        personalityLogger.info("Persönlichkeitsprofil zurückgesetzt")
    }

    // MARK: Private Helpers

    private func persist() {
        guard let profile else { return }
        var dict: [String: Any] = [:]
        // Scores als [String: Int] (OceanDimension.rawValue → Int)
        var scoresDict: [String: Int] = [:]
        for (dim, val) in profile.scores {
            scoresDict[dim.rawValue] = val
        }
        dict["scores"] = scoresDict
        if let ts = profile.completedAt?.timeIntervalSince1970 {
            dict["completedAt"] = ts
        }
        defaults.set(dict, forKey: storageKey)
    }

    private func load() {
        guard
            let dict = defaults.dictionary(forKey: storageKey),
            let rawScores = dict["scores"] as? [String: Int]
        else { return }

        var scores: [OceanDimension: Int] = [:]
        for (key, val) in rawScores {
            if let dim = OceanDimension(rawValue: key) {
                scores[dim] = val
            }
        }
        let completedAt: Date? = (dict["completedAt"] as? Double).map { Date(timeIntervalSince1970: $0) }
        profile = PersonalityProfile(scores: scores, completedAt: completedAt)
        personalityLogger.debug("Persönlichkeitsprofil geladen")
    }
}
