import Foundation

// MARK: - OceanDimension

/// Die fünf Dimensionen des Big-Five-Persönlichkeitsmodells (OCEAN).
enum OceanDimension: String, CaseIterable, Codable, Hashable {
    case openness          = "openness"
    case conscientiousness = "conscientiousness"
    case extraversion      = "extraversion"
    case agreeableness     = "agreeableness"
    case neuroticism       = "neuroticism"

    /// Kurzbezeichnung für den Pentagon-Chart (einstellig).
    var shortLabel: String {
        switch self {
        case .openness:          return "O"
        case .conscientiousness: return "G"
        case .extraversion:      return "E"
        case .agreeableness:     return "V"
        case .neuroticism:       return "A"
        }
    }

    /// Vollständiger Achsenbeschriftungs-Text im Pentagon-Chart.
    var axisLabel: String {
        switch self {
        case .openness:          return "Offen"
        case .conscientiousness: return "Verlässlich"
        case .extraversion:      return "Gesellig"
        case .agreeableness:     return "Verträglich"
        case .neuroticism:       return "Ausgeglichen"
        }
    }

    /// Anzeigename (vollständig, für Ergebnis-Screen).
    var displayName: String {
        switch self {
        case .openness:          return "Offenheit"
        case .conscientiousness: return "Verlässlichkeit"
        case .extraversion:      return "Geselligkeit"
        case .agreeableness:     return "Verträglichkeit"
        case .neuroticism:       return "Ausgeglichenheit"
        }
    }

    /// SF-Symbol-Name der Dimension.
    var icon: String {
        switch self {
        case .openness:          return "lightbulb.fill"
        case .conscientiousness: return "checkmark.seal.fill"
        case .extraversion:      return "person.2.fill"
        case .agreeableness:     return "heart.fill"
        case .neuroticism:       return "leaf.fill"
        }
    }
}

// MARK: - TraitLevel

/// Ausprägungsstufe eines OCEAN-Merkmals (0–2 Punkte pro Dimension).
enum TraitLevel: String, Codable, CaseIterable {
    case low    = "low"
    case medium = "medium"
    case high   = "high"

    static func from(score: Int) -> TraitLevel {
        switch score {
        case 0:  return .low
        case 1:  return .medium
        default: return .high
        }
    }
}

// MARK: - QuizQuestion

/// Eine einzelne Situationsfrage im Persönlichkeitsquiz.
/// Die Wahl zwischen optionA und optionB fließt mit `optionAScore` in die Dimension ein.
struct QuizQuestion: Identifiable {
    /// Stabiler String-Schlüssel, auch als Lokalisierungsschlüssel verwendet.
    let id: String
    let dimension: OceanDimension
    /// Situationstext (Lokalisierungsschlüssel).
    let situation: String
    /// Option A-Text (Lokalisierungsschlüssel).
    let optionA: String
    /// Option B-Text (Lokalisierungsschlüssel).
    let optionB: String
    /// Punkte, die Dimension erhält wenn Option A gewählt wird (0 oder 1).
    /// Option B ergibt automatisch `1 - optionAScore`.
    let optionAScore: Int

    // MARK: - 10 Fragen gemäß Big-Five-Spezifikation

    static let all: [QuizQuestion] = [
        // Offenheit O1
        QuizQuestion(
            id: "O1",
            dimension: .openness,
            situation: String(localized: "Ein Freund schlägt spontan eine Aktivität vor, die du noch nie gemacht hast."),
            optionA:   String(localized: "Du sagst sofort zu – neue Erfahrungen reizen dich."),
            optionB:   String(localized: "Du schlägst lieber etwas vor, das ihr beide gut kennt."),
            optionAScore: 1
        ),
        // Offenheit O2
        QuizQuestion(
            id: "O2",
            dimension: .openness,
            situation: String(localized: "In deinem Viertel gibt es ein neues Treffen – niemand, den du kennst, ist dabei."),
            optionA:   String(localized: "Du gehst einfach hin – Neugier auf fremde Menschen treibt dich."),
            optionB:   String(localized: "Du wartest, bis ein Bekannter mitkommt."),
            optionAScore: 1
        ),
        // Verlässlichkeit C1
        QuizQuestion(
            id: "C1",
            dimension: .conscientiousness,
            situation: String(localized: "Du hast einem Freund versprochen zu helfen. Am Morgen bist du müde."),
            optionA:   String(localized: "Du erscheinst wie abgemacht – dein Wort gilt."),
            optionB:   String(localized: "Du fragst kurz nach, ob es sich verschieben lässt."),
            optionAScore: 1
        ),
        // Verlässlichkeit C2
        QuizQuestion(
            id: "C2",
            dimension: .conscientiousness,
            situation: String(localized: "Nächste Woche hat eine Freundin Geburtstag."),
            optionA:   String(localized: "Du hast es dir sofort notiert und planst etwas Besonderes."),
            optionB:   String(localized: "Du reagierst spontan, wenn der Tag kommt."),
            optionAScore: 1
        ),
        // Geselligkeit E1
        QuizQuestion(
            id: "E1",
            dimension: .extraversion,
            situation: String(localized: "Nach einer anstrengenden Woche hast du einen freien Samstag."),
            optionA:   String(localized: "Du rufst spontan Freunde an und organisierst ein Treffen."),
            optionB:   String(localized: "Du genießt die Ruhe und tankst alleine auf."),
            optionAScore: 1
        ),
        // Geselligkeit E2
        QuizQuestion(
            id: "E2",
            dimension: .extraversion,
            situation: String(localized: "Auf einer Nachbarschaftsparty kennst du kaum jemanden."),
            optionA:   String(localized: "Du gehst aktiv auf Fremde zu und fängst Gespräche an."),
            optionB:   String(localized: "Du wartest, bis jemand dich anspricht."),
            optionAScore: 1
        ),
        // Verträglichkeit A1
        QuizQuestion(
            id: "A1",
            dimension: .agreeableness,
            situation: String(localized: "Ein Nachbar bittet um einen Gefallen, der dir gerade ungelegen kommt."),
            optionA:   String(localized: "Du hilfst trotzdem – anderen etwas Gutes tun liegt dir."),
            optionB:   String(localized: "Du erklärst ehrlich, dass es dir gerade nicht passt."),
            optionAScore: 1
        ),
        // Verträglichkeit A2
        QuizQuestion(
            id: "A2",
            dimension: .agreeableness,
            situation: String(localized: "Ein Freund erzählt von einem Plan, den du für einen Fehler hältst."),
            optionA:   String(localized: "Du unterstützt ihn und behältst deine Bedenken für dich."),
            optionB:   String(localized: "Du sprichst deine Sorgen an, auch wenn es Spannung erzeugt."),
            optionAScore: 1
        ),
        // Ausgeglichenheit N1 (invertiert: A = stabil = hohes N-inverted)
        QuizQuestion(
            id: "N1",
            dimension: .neuroticism,
            situation: String(localized: "Von einem guten Freund hast du zwei Wochen nichts gehört."),
            optionA:   String(localized: "Du meldest dich locker – er ist wahrscheinlich einfach beschäftigt."),
            optionB:   String(localized: "Du fragst dich, ob du etwas falsch gemacht hast, und das lässt dich nicht los."),
            optionAScore: 0   // A = emotional stabil = 0 Neurotizismus-Punkte
        ),
        // Ausgeglichenheit N2 (invertiert)
        QuizQuestion(
            id: "N2",
            dimension: .neuroticism,
            situation: String(localized: "Verabredungen mit Freunden fallen kurzfristig aus."),
            optionA:   String(localized: "Du zuckst die Schultern und findest schnell etwas anderes."),
            optionB:   String(localized: "Du bist enttäuscht und brauchst Zeit, um dich neu zu sortieren."),
            optionAScore: 0   // A = emotional stabil = 0 Neurotizismus-Punkte
        ),
    ]
}

// MARK: - PersonalityProfile

/// Ergebnis des OCEAN-Persönlichkeitsquiz.
/// Scores: 0–2 pro Dimension (Summe aus 2 Fragen à 0 oder 1 Punkt).
struct PersonalityProfile: Codable, Equatable {

    // MARK: Daten

    /// Rohpunkte je Dimension (0 = niedrig, 1 = mittel, 2 = hoch).
    let scores: [OceanDimension: Int]
    /// Zeitpunkt der letzten Quiz-Ausfüllung.
    let completedAt: Date?

    var isComplete: Bool { completedAt != nil }

    // MARK: Hilfsmethoden

    func level(for dimension: OceanDimension) -> TraitLevel {
        TraitLevel.from(score: scores[dimension] ?? 1)
    }

    /// Normalisierter Wert 0…1 für Pentagon-Chart-Vertex.
    func normalized(for dimension: OceanDimension) -> Double {
        let score = Double(scores[dimension] ?? 1)
        return score / 2.0   // 0→0.0, 1→0.5, 2→1.0
    }

    // MARK: Zusammenfassung (regelbasiert, kein API-Aufruf)

    /// Kurzer, warmer Zusammenfassungstext. Kein OCEAN-Fachjargon.
    var summaryText: String {
        let e = level(for: .extraversion)
        let o = level(for: .openness)
        let c = level(for: .conscientiousness)
        let a = level(for: .agreeableness)
        let n = level(for: .neuroticism)

        var parts: [String] = []

        // Sozialverhalten
        switch e {
        case .high:   parts.append("Du gehst offen auf Menschen zu und genießt Gesellschaft.")
        case .medium: parts.append("Du schätzt Gesellschaft, brauchst aber auch Zeit für dich.")
        case .low:    parts.append("Du findest Energie eher in der Stille als im Trubel.")
        }

        // Verlässlichkeit
        switch c {
        case .high:   parts.append("Anderen kannst du sich auf dich verlassen.")
        case .medium: parts.append("Du bist zuverlässig, wenn es darauf ankommt.")
        case .low:    parts.append("Du lebst gerne spontan und im Moment.")
        }

        // Offenheit
        switch o {
        case .high:   parts.append("Neue Erfahrungen und Ideen reizen dich.")
        case .medium: parts.append("Du bist offen für Neues, schätzt aber auch das Vertraute.")
        case .low:    parts.append("Du schätzt Bewährtes und Verlässliches.")
        }

        // Ausgeglichenheit (Neurotizismus inverted)
        switch n {
        case .low:    parts.append("Kleinen Rückschlägen begegnest du mit Gelassenheit.")
        case .medium: parts.append("Du findest nach Schwierigkeiten gut wieder in deine Mitte.")
        case .high:   parts.append("Du nimmst Dinge nah an dir wahr – das macht dich empathisch.")
        }

        // Verträglichkeit
        if a == .high {
            parts.append("Das Wohlergehen anderer liegt dir am Herzen.")
        }

        return parts.joined(separator: " ")
    }

    // MARK: Codable (Dictionary-Schlüssel als String)

    enum CodingKeys: String, CodingKey {
        case scores, completedAt
    }

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)
        // Encode OceanDimension keys as Strings
        let stringScores = Dictionary(uniqueKeysWithValues: scores.map { ($0.key.rawValue, $0.value) })
        try container.encode(stringScores, forKey: .scores)
        try container.encodeIfPresent(completedAt, forKey: .completedAt)
    }

    init(scores: [OceanDimension: Int], completedAt: Date?) {
        self.scores = scores
        self.completedAt = completedAt
    }

    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        let stringScores = try container.decode([String: Int].self, forKey: .scores)
        scores = Dictionary(uniqueKeysWithValues: stringScores.compactMap { key, val in
            guard let dim = OceanDimension(rawValue: key) else { return nil }
            return (dim, val)
        })
        completedAt = try container.decodeIfPresent(Date.self, forKey: .completedAt)
    }
}
