package pl.firmatpp.kierowca.data.upload

import android.content.Context
import androidx.room.migration.Migration
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.sqlite.db.SupportSQLiteDatabase
import pl.firmatpp.kierowca.data.sync.DriverBootstrapCacheEntity
import pl.firmatpp.kierowca.data.sync.DriverCacheDao
import pl.firmatpp.kierowca.data.sync.DriverRouteCacheEntity
import pl.firmatpp.kierowca.data.sync.DriverSyncStateEntity

@Database(
    entities = [
        PhotoUploadEntity::class,
        DriverBootstrapCacheEntity::class,
        DriverRouteCacheEntity::class,
        DriverSyncStateEntity::class,
    ],
    version = 2,
    exportSchema = false,
)
abstract class DriverDatabase : RoomDatabase() {
    abstract fun photoUploadDao(): PhotoUploadDao
    abstract fun driverCacheDao(): DriverCacheDao

    companion object {
        @Volatile
        private var instance: DriverDatabase? = null

        private val migration1To2 = object : Migration(1, 2) {
            override fun migrate(db: SupportSQLiteDatabase) {
                db.execSQL(
                    """
                    CREATE TABLE IF NOT EXISTS driver_bootstrap_cache (
                        date TEXT NOT NULL PRIMARY KEY,
                        payloadJson TEXT NOT NULL,
                        checksum TEXT,
                        version INTEGER,
                        syncedAtEpochMillis INTEGER NOT NULL
                    )
                    """.trimIndent(),
                )
                db.execSQL(
                    """
                    CREATE TABLE IF NOT EXISTS driver_route_cache (
                        routeId TEXT NOT NULL PRIMARY KEY,
                        payloadJson TEXT NOT NULL,
                        checksum TEXT,
                        version INTEGER,
                        syncedAtEpochMillis INTEGER NOT NULL
                    )
                    """.trimIndent(),
                )
                db.execSQL(
                    """
                    CREATE TABLE IF NOT EXISTS driver_sync_states (
                        key TEXT NOT NULL PRIMARY KEY,
                        scope TEXT NOT NULL,
                        date TEXT,
                        routeId TEXT,
                        checksum TEXT NOT NULL,
                        version INTEGER NOT NULL,
                        computedAt TEXT NOT NULL,
                        syncedAtEpochMillis INTEGER NOT NULL
                    )
                    """.trimIndent(),
                )
                db.execSQL("CREATE UNIQUE INDEX IF NOT EXISTS index_driver_sync_states_scope_date_routeId ON driver_sync_states(scope, date, routeId)")
            }
        }

        fun get(context: Context): DriverDatabase =
            instance ?: synchronized(this) {
                instance ?: Room.databaseBuilder(
                    context.applicationContext,
                    DriverDatabase::class.java,
                    "driver-local-outbox.db",
                ).addMigrations(migration1To2).build().also { instance = it }
            }
    }
}
