import Testing
import Foundation
@testable import nahbar

// MARK: - AutoStart Logic Tests

/// Helper: builds a coordinator with controlled version and tour list.
private func makeAutoCoordinator(
    tours: [Tour],
    currentVersion: String,
    lastSeenVersion: String? = nil
) -> (TourCoordinator, TourSeenStore) {
    let suiteName = "test.autostart.\(UUID().uuidString)"
    let defaults = UserDefaults(suiteName: suiteName)!
    let store = TourSeenStore(defaults: defaults)
    store.lastSeenAppVersion = lastSeenVersion
    let coordinator = TourCoordinator(tours: tours, seenStore: store, appVersionProvider: { currentVersion })
    return (coordinator, store)
}

/// Creates a minimal test tour with autoOnUpdate trigger.
private func makeUpdateTour(id: TourID, minVersion: String) -> Tour {
    Tour(
        id: id,
        title: "Test Tour",
        steps: [TourStep(title: "Step", body: "Body")],
        minAppVersion: minVersion,
        triggerMode: .autoOnUpdate
    )
}

/// Creates a minimal test tour with manualOnly trigger.
private func makeManualTour(id: TourID) -> Tour {
    Tour(
        id: id,
        title: "Manual Tour",
        steps: [TourStep(title: "Step", body: "Body")],
        minAppVersion: "1.0",
        triggerMode: .manualOnly
    )
}

@Suite("AutoStart – checkForPendingTours")
struct AutoStartLogicTests {

    @Test("Frische Installation (kein lastSeenVersion): autoOnUpdate-Tour wird gestartet")
    func freshInstallStartsUpdateTour() {
        let updateTour = makeUpdateTour(id: .v1_2_besuchsfragebogen, minVersion: "1.2")
        let (coordinator, _) = makeAutoCoordinator(
            tours: [updateTour],
            currentVersion: "1.2",
            lastSeenVersion: nil
        )
        coordinator.checkForPendingTours()
        #expect(coordinator.activeTour?.id == .v1_2_besuchsfragebogen)
    }

    @Test("Bereits gesehene Tour wird nicht erneut gestartet")
    func seenTourNotStartedAgain() {
        let updateTour = makeUpdateTour(id: .v1_2_besuchsfragebogen, minVersion: "1.2")
        let (coordinator, store) = makeAutoCoordinator(
            tours: [updateTour],
            currentVersion: "1.2",
            lastSeenVersion: nil
        )
        store.markSeen(.v1_2_besuchsfragebogen)
        coordinator.checkForPendingTours()
        #expect(!coordinator.isActive)
    }

    @Test("Tour mit minVersion == currentVersion wird gestartet (wenn lastSeen kleiner)")
    func tourWithCurrentVersionStarted() {
        let updateTour = makeUpdateTour(id: .v1_2_besuchsfragebogen, minVersion: "1.2")
        let (coordinator, _) = makeAutoCoordinator(
            tours: [updateTour],
            currentVersion: "1.2",
            lastSeenVersion: "1.0"
        )
        coordinator.checkForPendingTours()
        #expect(coordinator.isActive)
    }

    @Test("Tour mit minVersion < lastSeenVersion wird NICHT gestartet")
    func oldTourNotStartedAfterUpdate() {
        let updateTour = makeUpdateTour(id: .v1_2_besuchsfragebogen, minVersion: "1.2")
        let (coordinator, _) = makeAutoCoordinator(
            tours: [updateTour],
            currentVersion: "1.3",
            lastSeenVersion: "1.3"
        )
        coordinator.checkForPendingTours()
        #expect(!coordinator.isActive)
    }

    @Test("manualOnly-Tour wird von checkForPendingTours NIE gestartet")
    func manualOnlyTourNeverAutoStarts() {
        let manualTour = makeManualTour(id: .v1_3_personality)
        let (coordinator, _) = makeAutoCoordinator(
            tours: [manualTour],
            currentVersion: "1.3",
            lastSeenVersion: nil
        )
        coordinator.checkForPendingTours()
        #expect(!coordinator.isActive)
    }

    @Test("manualOrFirstLaunch-Tour wird von checkForPendingTours NIE gestartet")
    func manualOrFirstLaunchTourNeverAutoStarts() {
        // TourCatalog.onboarding is manualOrFirstLaunch
        let (coordinator, _) = makeAutoCoordinator(
            tours: [TourCatalog.onboarding],
            currentVersion: "1.0",
            lastSeenVersion: nil
        )
        coordinator.checkForPendingTours()
        #expect(!coordinator.isActive)
    }

    @Test("Mehrere pending Tours werden nacheinander abgearbeitet")
    func multiplePendingToursQueuedSequentially() {
        let tour1 = makeUpdateTour(id: .v1_2_besuchsfragebogen, minVersion: "1.2")
        let tour2 = makeUpdateTour(id: .v1_3_personality, minVersion: "1.3")
        let (coordinator, _) = makeAutoCoordinator(
            tours: [tour1, tour2],
            currentVersion: "1.3",
            lastSeenVersion: "1.0"
        )
        coordinator.checkForPendingTours()
        // First tour should be active
        #expect(coordinator.activeTour?.id == .v1_2_besuchsfragebogen)
        // Skip first, second should start
        coordinator.skip()
        #expect(coordinator.activeTour?.id == .v1_3_personality)
        // Skip second, no more tours
        coordinator.skip()
        #expect(!coordinator.isActive)
    }

    @Test("Nach Abschluss aller Pending-Touren wird lastSeenAppVersion auf currentVersion gesetzt")
    func lastSeenVersionUpdatedAfterAllToursComplete() {
        let updateTour = makeUpdateTour(id: .v1_2_besuchsfragebogen, minVersion: "1.2")
        let (coordinator, store) = makeAutoCoordinator(
            tours: [updateTour],
            currentVersion: "1.2",
            lastSeenVersion: "1.0"
        )
        coordinator.checkForPendingTours()
        coordinator.skip()
        #expect(store.lastSeenAppVersion == "1.2")
    }

    @Test("Manuelles start(.onboarding) ist unabhängig von checkForPendingTours")
    func manualStartIgnoresPendingLogic() {
        let (coordinator, _) = makeAutoCoordinator(
            tours: [TourCatalog.onboarding],
            currentVersion: "1.0",
            lastSeenVersion: nil
        )
        // checkForPendingTours should not start it
        coordinator.checkForPendingTours()
        #expect(!coordinator.isActive)
        // Manual start should work
        coordinator.start(.onboarding)
        #expect(coordinator.isActive)
    }
}
