//
//  UITestMode.swift
//  Reflect (iOS)
//
//  Handles launch arguments for UI testing mode.
//  When --ui-testing is passed, the app uses deterministic settings.
//

import Foundation
#if canImport(UIKit)
import UIKit
#endif

enum UITestMode {
    /// Whether the app was launched in UI testing mode
    static var isUITesting: Bool {
        ProcessInfo.processInfo.arguments.contains("--ui-testing")
    }

    /// Whether to reset all state before the test run
    static var shouldResetState: Bool {
        ProcessInfo.processInfo.arguments.contains("--reset-state")
    }

    /// Whether to disable animations for faster, more deterministic tests
    static var disableAnimations: Bool {
        ProcessInfo.processInfo.arguments.contains("--disable-animations")
    }

    /// Whether to bypass the subscription paywall
    static var bypassSubscription: Bool {
        ProcessInfo.processInfo.arguments.contains("--bypass-subscription")
    }

    /// Whether to skip onboarding
    static var skipOnboarding: Bool {
        ProcessInfo.processInfo.arguments.contains("--skip-onboarding")
    }

    /// Whether to force the trial to be expired (sets firstLaunchDate to 31 days ago)
    static var expireTrial: Bool {
        ProcessInfo.processInfo.arguments.contains("--expire-trial")
    }

    /// Seed fixture name if provided (via environment variable)
    static var seedFixture: String? {
        ProcessInfo.processInfo.environment["UI_TEST_FIXTURE"]
    }

    /// Apply all UI test mode settings. Called early in app startup.
    @MainActor
    static func configureIfNeeded() {
        guard isUITesting else { return }

        #if canImport(UIKit)
        if disableAnimations {
            UIView.setAnimationsEnabled(false)
        }
        #endif

        if shouldResetState {
            resetAppState()
        }

        if skipOnboarding {
            GroupUserDefaults.groupDefaults.set(false, forKey: UserDefaultsStore.Keys.needsOnboarding.rawValue)
        }

        if expireTrial {
            // Set firstLaunchDate to 31 days ago so the 30-day trial is expired.
            // Must run BEFORE IAPManager.shared is accessed so the async status
            // check sees the expired date.
            let expiredDate = Calendar.current.date(byAdding: .day, value: -31, to: Date())!
            GroupUserDefaults.groupDefaults.set(expiredDate, forKey: UserDefaultsStore.Keys.firstLaunchDate.rawValue)
            GroupUserDefaults.groupDefaults.synchronize()
        }

        #if DEBUG
        IAPManager.shared.bypassSubscription = bypassSubscription
        // Reset subscription state to discard stale cached state from previous test runs.
        // IAPManager.shared was already initialized (as @StateObject in ReflectApp) before
        // configureIfNeeded runs, so it may have restored stale subscription data.
        IAPManager.shared.resetForTesting()
        #endif

        // Seed fixture data if requested
        if let fixture = seedFixture {
            seedData(fixture: fixture)
        }
    }

    /// Reset all user defaults and persisted state for a clean test run
    @MainActor
    private static func resetAppState() {
        let defaults = GroupUserDefaults.groupDefaults
        // Clear group user defaults using the suite domain name
        defaults.removePersistentDomain(forName: Constants.currentGroupShareId)

        // Explicitly clear subscription cache keys that may survive removePersistentDomain
        // on app group suites (known reliability issue).
        defaults.removeObject(forKey: UserDefaultsStore.Keys.cachedSubscriptionExpiration.rawValue)
        defaults.removeObject(forKey: UserDefaultsStore.Keys.hasActiveSubscription.rawValue)
        defaults.removeObject(forKey: UserDefaultsStore.Keys.firstLaunchDate.rawValue)

        // Reset key defaults explicitly (true = fresh install state where onboarding is needed)
        defaults.set(true, forKey: UserDefaultsStore.Keys.needsOnboarding.rawValue)
        defaults.set(0, forKey: UserDefaultsStore.Keys.votingLayoutStyle.rawValue) // horizontal
        defaults.synchronize()

        // Clear standard user defaults
        UserDefaults.standard.set(false, forKey: "debug_bypassSubscription")

        // Clear all mood data
        DataController.shared.clearDB()
    }

    /// Seed the database with fixture data for deterministic tests
    @MainActor
    private static func seedData(fixture: String) {
        switch fixture {
        case "single_mood":
            // One entry for today with mood "Great"
            DataController.shared.add(mood: .great, forDate: Calendar.current.startOfDay(for: Date()), entryType: .listView)

        case "week_of_moods":
            // One mood per day for the last 7 days
            let moods: [Mood] = [.great, .good, .average, .bad, .horrible, .good, .great]
            for (offset, mood) in moods.enumerated() {
                let date = Calendar.current.date(byAdding: .day, value: -offset, to: Calendar.current.startOfDay(for: Date()))!
                DataController.shared.add(mood: mood, forDate: date, entryType: .listView)
            }

        case "empty":
            // No data — already cleared in resetAppState
            break

        default:
            break
        }
    }
}
