package com.fieldlabel.collector.di

import android.content.Context
import androidx.datastore.core.DataStore
import androidx.datastore.preferences.core.Preferences
import androidx.datastore.preferences.preferencesDataStore
import androidx.room.Room
import com.fieldlabel.collector.data.local.AppDatabase
import com.fieldlabel.collector.data.local.CollectionRecordDao
import com.fieldlabel.collector.data.local.CustomFieldDefDao
import com.fieldlabel.collector.data.local.CustomFieldValueDao
import com.fieldlabel.collector.data.local.GeocodeCacheDao
import com.fieldlabel.collector.data.local.RouteLogDao
import com.fieldlabel.collector.data.local.RoutePointDao
import com.fieldlabel.collector.data.local.SpecimenPhotoDao
import com.fieldlabel.collector.service.NominatimApi
import com.google.firebase.auth.FirebaseAuth
import com.google.firebase.auth.ktx.auth
import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.ktx.firestore
import com.google.firebase.ktx.Firebase
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory
import java.util.concurrent.TimeUnit
import javax.inject.Singleton

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

@Module
@InstallIn(SingletonComponent::class)
object AppModule {

    // ---- Room ----
    @Provides @Singleton
    fun provideDatabase(@ApplicationContext ctx: Context): AppDatabase =
        Room.databaseBuilder(ctx, AppDatabase::class.java, "collection_label.db")
            .addMigrations(
                AppDatabase.MIGRATION_1_2,
                AppDatabase.MIGRATION_2_3,
                AppDatabase.MIGRATION_3_4,
                AppDatabase.MIGRATION_4_5
            )
            .fallbackToDestructiveMigration()
            .build()

    @Provides @Singleton
    fun provideRecordDao(db: AppDatabase): CollectionRecordDao = db.collectionRecordDao()

    @Provides @Singleton
    fun provideGeocodeDao(db: AppDatabase): GeocodeCacheDao = db.geocodeCacheDao()

    @Provides @Singleton
    fun provideSpecimenPhotoDao(db: AppDatabase): SpecimenPhotoDao = db.specimenPhotoDao()

    @Provides @Singleton
    fun provideCustomFieldDefDao(db: AppDatabase): CustomFieldDefDao = db.customFieldDefDao()

    @Provides @Singleton
    fun provideCustomFieldValueDao(db: AppDatabase): CustomFieldValueDao = db.customFieldValueDao()

    @Provides @Singleton
    fun provideRouteLogDao(db: AppDatabase): RouteLogDao = db.routeLogDao()

    @Provides @Singleton
    fun provideRoutePointDao(db: AppDatabase): RoutePointDao = db.routePointDao()

    // ---- DataStore ----
    @Provides @Singleton
    fun provideDataStore(@ApplicationContext ctx: Context): DataStore<Preferences> =
        ctx.dataStore

    // ---- Firebase ----
    @Provides @Singleton
    fun provideFirestore(): FirebaseFirestore = Firebase.firestore

    @Provides @Singleton
    fun provideFirebaseAuth(): FirebaseAuth = Firebase.auth

    // ---- Nominatim (OkHttp + Retrofit) ----
    @Provides @Singleton
    fun provideOkHttpClient(): OkHttpClient =
        OkHttpClient.Builder()
            .connectTimeout(10, TimeUnit.SECONDS)
            .readTimeout(10, TimeUnit.SECONDS)
            .addInterceptor { chain ->
                // Nominatim 利用規約: User-Agent 必須
                val request = chain.request().newBuilder()
                    .header("User-Agent", "CollectionLabelApp/1.0 (kutu92xjoo@gmail.com)")
                    .build()
                chain.proceed(request)
            }
            .addInterceptor(HttpLoggingInterceptor().apply {
                level = HttpLoggingInterceptor.Level.BASIC
            })
            .build()

    @Provides @Singleton
    fun provideMoshi(): Moshi = Moshi.Builder()
        .add(KotlinJsonAdapterFactory())
        .build()

    @Provides @Singleton
    fun provideNominatimApi(client: OkHttpClient, moshi: Moshi): NominatimApi =
        Retrofit.Builder()
            .baseUrl("https://nominatim.openstreetmap.org/")
            .client(client)
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .build()
            .create(NominatimApi::class.java)
}
