package com.example.myapplication.database

import android.content.Context
import android.graphics.Bitmap
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.myapplication.database.remotekeys.dao.RemoteKeysDao
import com.example.myapplication.database.remotekeys.model.RemoteKeys
import com.example.myapplication.database.room.dao.bike.BikeDao
import com.example.myapplication.database.room.dao.item.ItemDao
import com.example.myapplication.database.room.dao.rent.RentDao
import com.example.myapplication.database.room.dao.rent.RentItemCrossRefDao
import com.example.myapplication.database.room.dao.user.UserDao
import com.example.myapplication.database.room.dao.user.UserItemCrossRefDao
import com.example.myapplication.database.room.model.bike.Bike
import com.example.myapplication.database.room.model.item.Item
import com.example.myapplication.database.room.model.rent.Rent
import com.example.myapplication.database.room.model.rent.RentItemCrossRef
import com.example.myapplication.database.room.model.user.User
import com.example.myapplication.database.room.model.user.UserItemCrossRef
import com.example.myapplication.setting.LocalDateTimeConverter
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.io.ByteArrayOutputStream

@Database(
    entities = [
        Bike::class,
        Item::class,
        Rent::class,
        RentItemCrossRef::class,
        User::class,
        UserItemCrossRef::class,
        RemoteKeys::class
    ],
    version = 1,
    exportSchema = false
)
@TypeConverters(LocalDateTimeConverter::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun bikeDao(): BikeDao
    abstract fun itemDao(): ItemDao
    abstract fun rentDao(): RentDao
    abstract fun rentItemCrossRefDao(): RentItemCrossRefDao
    abstract fun userDao(): UserDao
    abstract fun userItemCrossRefDao(): UserItemCrossRefDao
    abstract fun remoteKeysDao(): RemoteKeysDao

    companion object {
        private const val DB_NAME: String = "pmy-db"

        @Volatile
        private var INSTANCE: AppDatabase? = null

        private suspend fun populateDatabase() {
            INSTANCE?.let { database ->
                // Users
                val userDao = database.userDao()
                val user1 = User(1, "login", "admin", "password")
                userDao.insert(user1)

            }
        }

        fun getInstance(appContext: Context): AppDatabase {
            return INSTANCE ?: synchronized(this) {
                Room.databaseBuilder(
                    appContext,
                    AppDatabase::class.java,
                    DB_NAME
                )
                    .addCallback(object : Callback() {
                        override fun onCreate(db: SupportSQLiteDatabase) {
                            super.onCreate(db)
                            CoroutineScope(Dispatchers.IO).launch {
                                populateDatabase()
                            }
                        }
                    })
                    .build()
                    .also { INSTANCE = it }
            }
        }

        private fun createColoredImage(color: Int): ByteArray {
            val width = 100
            val height = 100

            val bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
            bmp.eraseColor(color)

            val stream = ByteArrayOutputStream()
            bmp.compress(Bitmap.CompressFormat.PNG, 100, stream)

            return stream.toByteArray()
        }

        private fun getRandomColorInt(): Int {
            val red = (0..255).random()
            val green = (0..255).random()
            val blue = (0..255).random()
            return (0xFF shl 24) or (red shl 16) or (green shl 8) or blue
        }

        private fun generateBikeName(index: Int): String {
            val base = 'a'.code
            val alphabetSize = 26
            val sb = StringBuilder()
            var remainder = index
            do {
                val letter = (remainder % alphabetSize + base).toChar()
                sb.insert(0, letter)
                remainder /= alphabetSize
            } while (remainder > 0)
            return sb.toString()
        }
    }
}