import Foundation
import SwiftUI
import ComposeApp

/// Simple factory-based dependency container for ViewModels and services.
/// Enables unit testing by allowing mock implementations to be injected.
///
/// Usage in production:
/// ```swift
/// let authVM = Dependencies.current.makeAuthViewModel()
/// ```
///
/// Usage in tests:
/// ```swift
/// Dependencies.testInstance = MockDependencies()
/// ```
@MainActor
final class Dependencies {
    // MARK: - Singleton

    static let shared = Dependencies()

    // MARK: - Test Support

    #if DEBUG
    /// Override with a mock instance for testing
    static var testInstance: Dependencies?

    /// Returns test instance if available, otherwise shared instance
    static var current: Dependencies {
        testInstance ?? shared
    }
    #else
    static var current: Dependencies { shared }
    #endif

    // MARK: - Private Init

    private init() {}

    // MARK: - Kotlin ViewModel Factories

    // SKIE doesn't expose Kotlin default constructor params to Swift, so
    // pass DataManager.shared explicitly on each factory.

    /// Create a new AuthViewModel instance
    func makeAuthViewModel() -> ComposeApp.AuthViewModel {
        ComposeApp.AuthViewModel(dataManager: ComposeApp.DataManager.shared)
    }

    /// Create a new ResidenceViewModel instance
    func makeResidenceViewModel() -> ComposeApp.ResidenceViewModel {
        ComposeApp.ResidenceViewModel(dataManager: ComposeApp.DataManager.shared)
    }

    /// Create a new TaskViewModel instance
    func makeTaskViewModel() -> ComposeApp.TaskViewModel {
        ComposeApp.TaskViewModel(dataManager: ComposeApp.DataManager.shared)
    }

    /// Create a new ContractorViewModel instance
    func makeContractorViewModel() -> ComposeApp.ContractorViewModel {
        ComposeApp.ContractorViewModel(
            dataManager: ComposeApp.DataManager.shared,
            initialSelectedContractorId: nil
        )
    }

    /// Create a new DocumentViewModel instance
    func makeDocumentViewModel() -> ComposeApp.DocumentViewModel {
        ComposeApp.DocumentViewModel(
            dataManager: ComposeApp.DataManager.shared,
            initialSelectedDocumentId: nil
        )
    }

    // MARK: - Service Factories

    /// Get the shared TokenStorage instance
    func makeTokenStorage() -> TokenStorageProtocol {
        TokenStorage.shared
    }
}

// MARK: - SwiftUI Environment Integration

private struct DependenciesKey: EnvironmentKey {
    @MainActor
    static let defaultValue = Dependencies.shared
}

extension EnvironmentValues {
    var dependencies: Dependencies {
        get { self[DependenciesKey.self] }
        set { self[DependenciesKey.self] = newValue }
    }
}

// MARK: - Mock Support for Testing

#if DEBUG
// To mock dependencies in tests, set Dependencies.testInstance to a new Dependencies()
// instance and override its factory methods using subclassing or protocol-based mocking.
// Since Dependencies is final for safety, use composition or protocol mocking instead.
#endif
