import Foundation
import Testing
@testable import nahbar

// MARK: - TourCatalog Tests

@Suite("TourCatalog – Validierung")
struct TourCatalogTests {

    @Test("Alle Touren haben mindestens 1 und höchstens 7 Steps")
    func allToursHaveValidStepCount() {
        for tour in TourCatalog.all {
            #expect(!tour.steps.isEmpty, "Tour \(tour.id.rawValue) hat keine Steps")
            #expect(tour.steps.count <= 7, "Tour \(tour.id.rawValue) hat mehr als 7 Steps")
        }
    }

    @Test("TourCatalog.tour(for:) gibt für jede bekannte TourID die richtige Tour zurück")
    func tourLookupByID() {
        // Only test IDs that are actually in TourCatalog.all
        for tour in TourCatalog.all {
            let found = TourCatalog.tour(for: tour.id)
            #expect(found != nil, "Keine Tour für ID \(tour.id.rawValue) gefunden")
            #expect(found?.id == tour.id)
        }
    }

    @Test("Onboarding-Tour hat genau 7 Steps")
    func onboardingTourHasSevenSteps() {
        #expect(TourCatalog.onboarding.steps.count == 7)
    }

    @Test("Onboarding-Tour hat triggerMode .manualOrFirstLaunch")
    func onboardingTourTriggerMode() {
        #expect(TourCatalog.onboarding.triggerMode == .manualOrFirstLaunch)
    }

    @Test("Onboarding-Tour hat minAppVersion '1.0'")
    func onboardingTourMinVersion() {
        #expect(TourCatalog.onboarding.minAppVersion == "1.0")
    }

    @Test("TourCatalog.all enthält mindestens eine Tour")
    func catalogIsNotEmpty() {
        #expect(!TourCatalog.all.isEmpty)
    }

    @Test("Alle Tour-IDs im Catalog sind eindeutig")
    func catalogIDsAreUnique() {
        let ids = TourCatalog.all.map { $0.id }
        let uniqueIDs = Set(ids)
        #expect(ids.count == uniqueIDs.count)
    }

    @Test("Alle Steps einer Tour haben eindeutige IDs")
    func stepIDsAreUniquePerTour() {
        for tour in TourCatalog.all {
            let stepIDs = tour.steps.map { $0.id }
            let uniqueIDs = Set(stepIDs)
            #expect(stepIDs.count == uniqueIDs.count, "Tour \(tour.id.rawValue) hat doppelte Step-IDs")
        }
    }
}

// MARK: - TourStep Target Tests

@Suite("TourCatalog – Step-Targets")
struct TourStepTargetTests {

    @Test("Onboarding-Step 4 (Index 3) targetet .addMomentButton")
    func step4TargetsAddMomentButton() {
        let steps = TourCatalog.onboarding.steps
        #expect(steps.count > 3)
        #expect(steps[3].target == .addMomentButton)
    }

    @Test("Onboarding-Step 5 (Index 4) targetet .addTodoButton")
    func step5TargetsAddTodoButton() {
        let steps = TourCatalog.onboarding.steps
        #expect(steps.count > 4)
        #expect(steps[4].target == .addTodoButton)
    }

    @Test("Schritte mit addMomentButton und addTodoButton haben CardPosition .below")
    func momentAndTodoStepsAreBelow() {
        let steps = TourCatalog.onboarding.steps
        let momentStep = steps.first { $0.target == .addMomentButton }
        let todoStep   = steps.first { $0.target == .addTodoButton }
        #expect(momentStep?.preferredCardPosition == .below)
        #expect(todoStep?.preferredCardPosition == .below)
    }

    @Test("Genau ein Step targetet .addMomentButton")
    func exactlyOneAddMomentStep() {
        let count = TourCatalog.onboarding.steps.filter { $0.target == .addMomentButton }.count
        #expect(count == 1)
    }

    @Test("Genau ein Step targetet .addTodoButton")
    func exactlyOneAddTodoStep() {
        let count = TourCatalog.onboarding.steps.filter { $0.target == .addTodoButton }.count
        #expect(count == 1)
    }
}

// MARK: - Tour Model Tests

@Suite("Tour – Preconditions")
struct TourModelTests {

    @Test("Tour mit 6 Steps kann erstellt werden")
    func tourWithSixStepsIsValid() {
        let steps = (0..<6).map { _ in
            TourStep(title: "test", body: "body")
        }
        let tour = Tour(
            id: .onboarding,
            title: "test",
            steps: steps,
            minAppVersion: "1.0",
            triggerMode: .manualOrFirstLaunch
        )
        #expect(tour.steps.count == 6)
    }

    @Test("Tour-Gleichheit basiert auf ID")
    func tourEqualityBasedOnID() {
        let step = TourStep(title: "t", body: "b")
        let tourA = Tour(id: .onboarding, title: "A", steps: [step], minAppVersion: "1.0", triggerMode: .manualOrFirstLaunch)
        let tourB = Tour(id: .onboarding, title: "B", steps: [step], minAppVersion: "1.1", triggerMode: .autoOnUpdate)
        #expect(tourA == tourB)
    }
}
