import Testing
import Foundation
@testable import nahbar

// MARK: - AppGroup Tests
//
// Testet die Shared-UserDefaults-Queue zwischen Hauptapp und Share Extension.
// Wichtig: Tests verwenden eigene UserDefaults-Suite um Produktionsdaten
// nicht zu beeinflussen.

@Suite("AppGroup – Pending Moments Queue")
struct AppGroupQueueTests {

    // Nutzt eine isolierte UserDefaults-Suite für jeden Test
    private let testDefaults = UserDefaults(suiteName: "nahbar.test.queue")!

    // Cleanup vor jedem Test
    init() {
        testDefaults.removeObject(forKey: "pendingMoments")
        testDefaults.removeObject(forKey: "cachedPeople")
    }

    @Test("pendingMoments ist initial leer")
    func pendingMomentsInitiallyEmpty() {
        // Die echte AppGroup-Queue kann Einträge aus vorherigen Tests enthalten,
        // daher testen wir die Serialisierungslogik direkt
        let emptyData = try! JSONSerialization.data(withJSONObject: [[String: String]]())
        testDefaults.set(emptyData, forKey: "pendingMoments")

        guard let data = testDefaults.data(forKey: "pendingMoments"),
              let array = try? JSONSerialization.jsonObject(with: data) as? [[String: String]]
        else {
            Issue.record("Konnte pendingMoments nicht lesen")
            return
        }
        #expect(array.isEmpty)
    }

    @Test("JSON-Serialisierung eines Moment-Eintrags ist korrekt")
    func momentEntrySerializationIsCorrect() throws {
        let personID = UUID()
        let entry: [String: String] = [
            "personID":   personID.uuidString,
            "personName": "Max Mustermann",
            "text":       "Neuer Moment",
            "type":       MomentType.conversation.rawValue,
        ]

        let queue = [entry]
        let data = try JSONSerialization.data(withJSONObject: queue)
        let decoded = try JSONSerialization.jsonObject(with: data) as! [[String: String]]

        #expect(decoded.count == 1)
        #expect(decoded[0]["personID"] == personID.uuidString)
        #expect(decoded[0]["personName"] == "Max Mustermann")
        #expect(decoded[0]["text"] == "Neuer Moment")
        #expect(decoded[0]["type"] == MomentType.conversation.rawValue)
    }

    @Test("Mehrere Einträge werden korrekt serialisiert")
    func multipleEntriesAreSerialized() throws {
        var queue: [[String: String]] = []
        for i in 0..<5 {
            queue.append([
                "personID":   UUID().uuidString,
                "personName": "Person \(i)",
                "text":       "Moment \(i)",
                "type":       MomentType.conversation.rawValue,
            ])
        }
        let data = try JSONSerialization.data(withJSONObject: queue)
        let decoded = try JSONSerialization.jsonObject(with: data) as! [[String: String]]
        #expect(decoded.count == 5)
        for i in 0..<5 {
            #expect(decoded[i]["personName"] == "Person \(i)")
        }
    }

    @Test("UUID-String ist gültig und round-trip-fähig")
    func uuidStringIsValidAndRoundTrips() {
        let original = UUID()
        let str = original.uuidString
        let parsed = UUID(uuidString: str)
        #expect(parsed == original)
    }

    @Test("source ist optional und fehlt bei nil korrekt im Dictionary")
    func sourceIsOptionalInDictionary() throws {
        var entry: [String: String] = [
            "personID":   UUID().uuidString,
            "personName": "Test",
            "text":       "Test",
            "type":       MomentType.thought.rawValue,
        ]
        // source NICHT hinzufügen

        let data = try JSONSerialization.data(withJSONObject: [entry])
        let decoded = try JSONSerialization.jsonObject(with: data) as! [[String: String]]
        #expect(decoded[0]["source"] == nil)

        // Jetzt mit source
        entry["source"] = MomentSource.whatsapp.rawValue
        let data2 = try JSONSerialization.data(withJSONObject: [entry])
        let decoded2 = try JSONSerialization.jsonObject(with: data2) as! [[String: String]]
        #expect(decoded2[0]["source"] == MomentSource.whatsapp.rawValue)
    }
}

// MARK: - AppGroup cachedPeople Tests

@Suite("AppGroup – cachedPeople Serialisierung")
struct AppGroupCachedPeopleTests {

    @Test("Personenliste wird korrekt serialisiert und deserialisiert")
    func peopleListSerializationRoundTrip() throws {
        let people: [[String: String]] = [
            ["id": UUID().uuidString, "name": "Anna Meier",  "tag": PersonTag.family.rawValue],
            ["id": UUID().uuidString, "name": "Ben Schulz",  "tag": PersonTag.friends.rawValue],
            ["id": UUID().uuidString, "name": "Carla Wagner", "tag": PersonTag.work.rawValue],
        ]

        let data = try JSONSerialization.data(withJSONObject: people)
        let decoded = try JSONSerialization.jsonObject(with: data) as! [[String: String]]

        #expect(decoded.count == 3)
        #expect(decoded[0]["name"] == "Anna Meier")
        #expect(decoded[1]["tag"] == PersonTag.friends.rawValue)
        #expect(UUID(uuidString: decoded[2]["id"]!) != nil)
    }

    @Test("Leere Personenliste ist gültig")
    func emptyPeopleListIsValid() throws {
        let empty: [[String: String]] = []
        let data = try JSONSerialization.data(withJSONObject: empty)
        let decoded = try JSONSerialization.jsonObject(with: data) as! [[String: String]]
        #expect(decoded.isEmpty)
    }
}
