package com.example.shawarma.data.db

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import androidx.sqlite.db.SupportSQLiteDatabase
import com.example.shawarma.data.dao.OrderDao
import com.example.shawarma.data.dao.OrderProductDao
import com.example.shawarma.data.dao.ProductDao
import com.example.shawarma.data.dao.UserDao
import com.example.shawarma.data.models.OrderModel
import com.example.shawarma.data.models.OrderProductModel
import com.example.shawarma.data.models.OrderStatus
import com.example.shawarma.data.models.ProductModel
import com.example.shawarma.data.models.UserModel
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.Date

@Database(
    entities =
    [
        UserModel::class,
        OrderModel::class,
        ProductModel::class,
        OrderProductModel::class,
    ],
    version = 1,
    exportSchema = false
)
@TypeConverters(Converter::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun userDao() : UserDao
    abstract fun productDao() : ProductDao
    abstract fun orderDao() : OrderDao
    abstract fun orderProductDao() : OrderProductDao

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

        @Volatile
        private var INSTANCE: AppDatabase? = null

        private suspend fun populateDatabase() {
            INSTANCE?.let { database ->
                // Users
                val userDao = database.userDao()
                val user1 = UserModel(1, "danya", "password", "ADMIN")
                userDao.insert(user1)
                // Products
                val productDao = database.productDao()
                val product1 = ProductModel(1, "Классик", 100, null)
                val product2 = ProductModel(2, "Сырная", 120, null)
                val discount1 = ProductModel(3, "Выгода", 80, 100)
                val discount2 = ProductModel(4, "Кола", 50, 75)
                productDao.insert(product1)
                productDao.insert(product2)
                productDao.insert(discount1)
                productDao.insert(discount2)
                // Orders
                val orderDao = database.orderDao()
                val order1 = OrderModel(1, OrderStatus.Готовится.toString(), 1, Date())
                val order2 = OrderModel(2, OrderStatus.Неоплачено.toString(), 1, Date())
                val order3 = OrderModel(3, OrderStatus.Готово.toString(), 1, Date())
                val order4 = OrderModel(4, OrderStatus.Выдано.toString(), 1, Date())
                orderDao.insert(order1)
                orderDao.insert(order2)
                orderDao.insert(order3)
                orderDao.insert(order4)
                // OrderProducts
                val orderProductDao = database.orderProductDao()
                val op1 = OrderProductModel(1, 1, 2, 200)
                val op2 = OrderProductModel(1, 4, 3, 150)
                val op3 = OrderProductModel(1, 3, 1, 80)
                val op4 = OrderProductModel(2, 1, 2, 200)
                val op5 = OrderProductModel(2, 4, 3, 150)
                val op6 = OrderProductModel(2, 3, 1, 80)
                val op7 = OrderProductModel(3, 1, 2, 200)
                val op8 = OrderProductModel(3, 4, 3, 150)
                val op9 = OrderProductModel(3, 3, 1, 80)
                val op10 = OrderProductModel(4, 1, 2, 200)
                val op11 = OrderProductModel(4, 4, 3, 150)
                val op12 = OrderProductModel(4, 3, 1, 80)
                orderProductDao.insert(op1)
                orderProductDao.insert(op2)
                orderProductDao.insert(op3)
                orderProductDao.insert(op4)
                orderProductDao.insert(op5)
                orderProductDao.insert(op6)
                orderProductDao.insert(op7)
                orderProductDao.insert(op8)
                orderProductDao.insert(op9)
                orderProductDao.insert(op10)
                orderProductDao.insert(op11)
                orderProductDao.insert(op12)
            }
        }

        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 }
            }
        }
    }

}