package com.fabledsword.minstrel.cache.db

import android.content.Context
import androidx.room.Room
import com.fabledsword.minstrel.cache.db.dao.AudioCacheIndexDao
import com.fabledsword.minstrel.cache.db.dao.AuthSessionDao
import com.fabledsword.minstrel.cache.db.dao.CachedAlbumDao
import com.fabledsword.minstrel.cache.db.dao.CachedArtistDao
import com.fabledsword.minstrel.cache.db.dao.CachedHistorySnapshotDao
import com.fabledsword.minstrel.cache.db.dao.CachedHomeIndexDao
import com.fabledsword.minstrel.cache.db.dao.CachedLikeDao
import com.fabledsword.minstrel.cache.db.dao.CachedMutationDao
import com.fabledsword.minstrel.cache.db.dao.DiagnosticEventDao
import com.fabledsword.minstrel.cache.db.dao.CachedPlaylistDao
import com.fabledsword.minstrel.cache.db.dao.CachedPlaylistTrackDao
import com.fabledsword.minstrel.cache.db.dao.CachedQuarantineDao
import com.fabledsword.minstrel.cache.db.dao.CachedResumeStateDao
import com.fabledsword.minstrel.cache.db.dao.CachedTrackDao
import com.fabledsword.minstrel.cache.db.dao.SyncMetadataDao
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.qualifiers.ApplicationContext
import dagger.hilt.components.SingletonComponent
import javax.inject.Singleton

@Module
@InstallIn(SingletonComponent::class)
@Suppress("TooManyFunctions") // Hilt @Provides bridges per DAO; one per family.
object DatabaseModule {
    @Provides
    @Singleton
    fun provideDatabase(@ApplicationContext context: Context): AppDatabase =
        Room.databaseBuilder(context, AppDatabase::class.java, DATABASE_NAME)
            // Pre-v1 safety net: rebuild on any schema mismatch. The sync
            // controller refills the cache from the server on first
            // launch, so users lose only the unsynced mutation queue
            // (acceptable while we're iterating). Replace with explicit
            // Migration entries before the first tagged release.
            .fallbackToDestructiveMigration(dropAllTables = true)
            .build()

    // DAO @Provides — Hilt can't inject AppDatabase abstract accessors
    // directly. Each consumer-needed DAO gets a thin @Provides bridge.
    @Provides
    @Singleton
    fun provideAuthSessionDao(db: AppDatabase): AuthSessionDao = db.authSessionDao()

    @Provides
    @Singleton
    fun provideCachedArtistDao(db: AppDatabase): CachedArtistDao = db.cachedArtistDao()

    @Provides
    @Singleton
    fun provideCachedAlbumDao(db: AppDatabase): CachedAlbumDao = db.cachedAlbumDao()

    @Provides
    @Singleton
    fun provideCachedTrackDao(db: AppDatabase): CachedTrackDao = db.cachedTrackDao()

    @Provides
    @Singleton
    fun provideCachedResumeStateDao(db: AppDatabase): CachedResumeStateDao =
        db.cachedResumeStateDao()

    @Provides
    @Singleton
    fun provideCachedHomeIndexDao(db: AppDatabase): CachedHomeIndexDao =
        db.cachedHomeIndexDao()

    @Provides
    @Singleton
    fun provideCachedHistorySnapshotDao(db: AppDatabase): CachedHistorySnapshotDao =
        db.cachedHistorySnapshotDao()

    @Provides
    @Singleton
    fun provideCachedQuarantineDao(db: AppDatabase): CachedQuarantineDao =
        db.cachedQuarantineDao()

    @Provides
    @Singleton
    fun provideCachedPlaylistDao(db: AppDatabase): CachedPlaylistDao =
        db.cachedPlaylistDao()

    @Provides
    @Singleton
    fun provideCachedPlaylistTrackDao(db: AppDatabase): CachedPlaylistTrackDao =
        db.cachedPlaylistTrackDao()

    @Provides
    @Singleton
    fun provideCachedLikeDao(db: AppDatabase): CachedLikeDao = db.cachedLikeDao()

    @Provides
    @Singleton
    fun provideCachedMutationDao(db: AppDatabase): CachedMutationDao =
        db.cachedMutationDao()

    @Provides
    @Singleton
    fun provideSyncMetadataDao(db: AppDatabase): SyncMetadataDao = db.syncMetadataDao()

    @Provides
    @Singleton
    fun provideAudioCacheIndexDao(db: AppDatabase): AudioCacheIndexDao =
        db.audioCacheIndexDao()

    @Provides
    @Singleton
    fun provideDiagnosticEventDao(db: AppDatabase): DiagnosticEventDao =
        db.diagnosticEventDao()

    private const val DATABASE_NAME = "minstrel.db"
}
