package com.example.livingai.di

import android.content.Context
import android.util.Log
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore
import androidx.window.layout.WindowMetricsCalculator
import coil.ImageLoader
import coil.decode.SvgDecoder
import com.example.livingai.data.camera.DefaultCaptureHandler
import com.example.livingai.data.camera.DefaultMeasurementCalculator
import com.example.livingai.data.camera.DefaultOrientationChecker
import com.example.livingai.data.camera.DefaultTiltChecker
import com.example.livingai.data.camera.MockPoseAnalyzer
import com.example.livingai.data.camera.TFLiteObjectDetector
import com.example.livingai.data.local.CSVDataSource
import com.example.livingai.data.ml.AIModelImpl
import com.example.livingai.data.repository.AppDataRepositoryImpl
import com.example.livingai.data.repository.business.AnimalDetailsRepositoryImpl
import com.example.livingai.data.repository.business.AnimalProfileRepositoryImpl
import com.example.livingai.data.repository.business.AnimalRatingRepositoryImpl
import com.example.livingai.data.repository.media.CameraRepositoryImpl
import com.example.livingai.data.repository.media.VideoRepositoryImpl
import com.example.livingai.domain.camera.CaptureHandler
import com.example.livingai.domain.camera.MeasurementCalculator
import com.example.livingai.domain.camera.OrientationChecker
import com.example.livingai.domain.camera.PoseAnalyzer
import com.example.livingai.domain.camera.TiltChecker
import com.example.livingai.domain.ml.AIModel
import com.example.livingai.domain.ml.AnalyzerThresholds
import com.example.livingai.domain.ml.FeedbackAnalyzer
import com.example.livingai.domain.ml.FeedbackAnalyzerImpl
import com.example.livingai.domain.ml.ObjectDetector
import com.example.livingai.domain.ml.ObjectDetectorImpl
import com.example.livingai.domain.repository.AppDataRepository
import com.example.livingai.domain.repository.CameraRepository
import com.example.livingai.domain.repository.VideoRepository
import com.example.livingai.domain.repository.business.AnimalDetailsRepository
import com.example.livingai.domain.repository.business.AnimalProfileRepository
import com.example.livingai.domain.repository.business.AnimalRatingRepository
import com.example.livingai.domain.repository.business.DataSource
import com.example.livingai.domain.usecases.AppDataUseCases
import com.example.livingai.domain.usecases.DeleteAnimalProfile
import com.example.livingai.domain.usecases.GetAnimalDetails
import com.example.livingai.domain.usecases.GetAnimalProfiles
import com.example.livingai.domain.usecases.GetAnimalRatings
import com.example.livingai.domain.usecases.GetSettingsUseCase
import com.example.livingai.domain.usecases.ProfileEntry.ProfileEntryUseCase
import com.example.livingai.domain.usecases.ProfileListing.ProfileListingUseCase
import com.example.livingai.domain.usecases.ReadAppEntryUseCase
import com.example.livingai.domain.usecases.SaveAppEntryUseCase
import com.example.livingai.domain.usecases.SaveSettingsUseCase
import com.example.livingai.domain.usecases.SetAnimalDetails
import com.example.livingai.domain.usecases.SetAnimalRatings
import com.example.livingai.pages.addprofile.AddProfileViewModel
import com.example.livingai.pages.camera.CameraViewModel
import com.example.livingai.pages.camera.VideoViewModel
import com.example.livingai.pages.home.HomeViewModel
import com.example.livingai.pages.imagepreview.ImagePreviewViewModel
import com.example.livingai.pages.listings.ListingsViewModel
import com.example.livingai.pages.onboarding.OnBoardingViewModel
import com.example.livingai.pages.ratings.RatingViewModel
import com.example.livingai.pages.settings.SettingsViewModel
import com.example.livingai.pages.videopreview.VideoPreviewViewModel
import com.example.livingai.utils.Constants
import com.example.livingai.utils.CoroutineDispatchers
import com.example.livingai.utils.DefaultCoroutineDispatchers
import com.example.livingai.utils.ScreenDimensions
import com.example.livingai.utils.SilhouetteManager
import com.example.livingai.utils.TiltSensorManager
import org.koin.android.ext.koin.androidContext
import org.koin.core.module.dsl.viewModel
import org.koin.dsl.module

private val Context.dataStore: DataStore<Preferences> by preferencesDataStore(name = Constants.USER_SETTINGS)

val appModule = module {

    single<DataStore<Preferences>> { androidContext().dataStore }

    single<AppDataRepository> { AppDataRepositoryImpl(get()) }

    single {
        AppDataUseCases(
            getSettings = GetSettingsUseCase(get()),
            saveSettings = SaveSettingsUseCase(get()),
            readAppEntry = ReadAppEntryUseCase(get()),
            saveAppEntry = SaveAppEntryUseCase(get())
        )
    }
    
    // Coroutine dispatchers (for testability)
    single<CoroutineDispatchers> { DefaultCoroutineDispatchers() }

    // Data Source
    single<DataSource> { 
        CSVDataSource(
            context = androidContext(),
            fileName = Constants.ANIMAL_DATA_FILENAME,
            dispatchers = get()
        ) 
    }

    // Coil ImageLoader singleton
    single {
        ImageLoader.Builder(androidContext())
            .components {
                add(SvgDecoder.Factory())
            }
            .build()
    }

    factory<OrientationChecker> { DefaultOrientationChecker() }
    factory<TiltChecker> { DefaultTiltChecker() }
    factory<com.example.livingai.domain.camera.ObjectDetector> { TFLiteObjectDetector(androidContext()) }
    factory<PoseAnalyzer> { MockPoseAnalyzer() }

    // Handlers
    factory<CaptureHandler> { DefaultCaptureHandler() }
    factory<MeasurementCalculator> { DefaultMeasurementCalculator() }

    // Initialize silhouettes once
    single<ScreenDimensions>(createdAtStart = true) {
        val ctx: Context = androidContext()
        val metrics = WindowMetricsCalculator.getOrCreate()
            .computeCurrentWindowMetrics(ctx)

        val bounds = metrics.bounds
        val screenWidth = bounds.width()
        val screenHeight = bounds.height()
        SilhouetteManager.initialize(ctx, screenWidth, screenHeight)
        ScreenDimensions(screenWidth, screenHeight)
    }

    // ML Model
    single<AIModel> { AIModelImpl(androidContext()) }
    single<ObjectDetector> { 
        ObjectDetectorImpl(
            context = androidContext(),
            onResults = { _, _ -> }, // Callback will be set by ViewModel
            onError = { error -> Log.e("ObjectDetector", "Error: $error") }
        )
    }
    
    single<FeedbackAnalyzer> { FeedbackAnalyzerImpl(AnalyzerThresholds()) }

    single { TiltSensorManager(androidContext()) }

    // Repositories
    single<AnimalProfileRepository> { AnimalProfileRepositoryImpl(get()) }
    single<AnimalDetailsRepository> { AnimalDetailsRepositoryImpl(get()) }
    single<AnimalRatingRepository> { AnimalRatingRepositoryImpl(get()) }
    single<CameraRepository> { CameraRepositoryImpl(get(), get(), androidContext()) }
    single<VideoRepository> { VideoRepositoryImpl(get()) }

    // Use Cases
    single { GetAnimalProfiles(get()) }
    single { GetAnimalDetails(get()) }
    single { GetAnimalRatings(get()) }
    single { SetAnimalDetails(get()) }
    single { SetAnimalRatings(get()) }
    single { DeleteAnimalProfile(get()) }

    //Use Cases
    single {
        ProfileEntryUseCase(
            getAnimalDetails = GetAnimalDetails(get()),
            setAnimalDetails = SetAnimalDetails(get())
        )
    }

    single {
        ProfileListingUseCase(
            getAnimalProfiles = GetAnimalProfiles(get()),
            deleteAnimalProfile = DeleteAnimalProfile(get())
        )
    }

    // ViewModels
    viewModel { HomeViewModel(get()) }
    viewModel { OnBoardingViewModel(get()) }
    viewModel { (savedStateHandle: androidx.lifecycle.SavedStateHandle?) -> 
        AddProfileViewModel(get(), get(), get(), androidContext(), savedStateHandle) 
    }
    viewModel { ListingsViewModel(get()) }
    viewModel { SettingsViewModel(get()) }
    viewModel { RatingViewModel(get(), get(), get(), get()) }
    viewModel { CameraViewModel(get(), get(), get(), get(), get(), get(), get(), get()) }
    viewModel { VideoViewModel(get(), get(), get()) }
    viewModel { ImagePreviewViewModel() }
    viewModel { VideoPreviewViewModel() }
}
