package com.webtoonviewer.work

import android.content.Context
import android.util.Log
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import com.google.gson.Gson
import com.webtoonviewer.db.Book
import com.webtoonviewer.repository.BookInformation
import com.webtoonviewer.network.SmbClientHelper
import com.webtoonviewer.repository.BookRepository
import com.webtoonviewer.storage.StorageManager
import com.webtoonviewer.utils.SharedPreferencesHelper
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.BufferedReader
import java.io.InputStreamReader

class UpdateBooks(context: Context, workerParams: WorkerParameters) :
    CoroutineWorker(context, workerParams) {
    private val smbClientHelper: SmbClientHelper = SmbClientHelper(context)
    private val bookRepository: BookRepository = BookRepository(context)
    private val bookIdPreferences: SharedPreferencesHelper = SharedPreferencesHelper(context, "book_id")

    private var isConnected = false

    override suspend fun doWork(): Result {
        val context = applicationContext

        //bookRepository.setAutoIncrement(40)

        updateIsLocal(context)

        try {
            isConnected = smbClientHelper.connect()
            if (isConnected) {
                val webtoonsShouldDeleted: MutableList<String> = bookRepository.getAllBookTitles()
                val newWebtoons: MutableList<String> = mutableListOf()


                for (item in smbClientHelper.getTitlesFromShare()) {
                    if (item.fileName != "." && item.fileName != "..") {

                        val title = item.fileName
                        val book = bookRepository.getBookByTitle(title)

                        if (book != null) {
                            val id = bookIdPreferences.readData(book.title, "0").toInt()
                            if (id != book.id) {
                                bookIdPreferences.saveData(book.title, book.id.toString())
                            }
                            webtoonsShouldDeleted.remove(title)
                            updateChapters(book)
                            updateTag(book)
                        } else { // newBook
                            newWebtoons.add(title)
                        }
                    }
                }
                for (webtoonTitle in webtoonsShouldDeleted) {
                    val bookId = bookIdPreferences.readData(webtoonTitle, "0").toInt()
                    if (bookRepository.getBookById(bookId)?.title == webtoonTitle) {
                        bookRepository.deleteBookById(bookId)
                    } else {
                        Log.d("UpdateBook", "Error webtoonsShouldDeleted: $bookId")
                    }
                }

                val missingIds = missingIds()

                for (webtoonTitle in newWebtoons) {
                    var webtoonId = bookRepository.getAllBookTitles().size + 1
                    if (missingIds.size > 0) {
                        webtoonId = missingIds[0]
                        missingIds.removeAt(0)

                    }
                    addNewBook(webtoonTitle, webtoonId)
                    val book = bookRepository.getBookByTitle(webtoonTitle)
                    if (book != null) {
                        bookIdPreferences.saveData(webtoonTitle, book.id.toString())
                        updateChapters(book)
                    }
                }

                synchronizeBooks(context)
            }
        } catch (e: Exception) {
            Log.e("SMB", "Error accessing SMB share", e)
        } finally {
            if (isConnected) {
                smbClientHelper.disconnect()
            }
        }
        return Result.success()
    }

    private suspend fun addNewBook(title: String, id: Int) {
        val informationFile = smbClientHelper.getInformationFile(title)

        informationFile.use { smbFile ->
            val reader = BufferedReader(InputStreamReader(smbFile.inputStream))
            val content = reader.use { it.readText() }
            val gson = Gson()
            val information = gson.fromJson(content, BookInformation::class.java)
            bookRepository.addNewBook(Book(
                id,
                title,
                information.author,
                information.description,
                information.tag,
                information.thumbnail_name,
                0))
        }
    }

    private suspend fun updateTag(book: Book) {
        val informationFile = smbClientHelper.getInformationFile(book.title)

        informationFile.use { smbFile ->
            val reader = BufferedReader(InputStreamReader(smbFile.inputStream))
            val content = reader.use { it.readText() }
            val gson = Gson()
            val informationFromFile = gson.fromJson(content, BookInformation::class.java)
            val tag = informationFromFile.tag
            if (tag != book.tag) {
                val information = BookInformation(book.title, book.author, tag, book.description, book.img)
                bookRepository.updateInformationById(book.id, information)
            }
        }
    }

    private suspend fun updateChapters(book: Book) {
        val count = smbClientHelper.getChapterSumFromShare(book.title)
        val dbChapterSum = book.chapterSum
        if (count != dbChapterSum) {
            var chapters = mutableListOf<String>()
            for (itemT in smbClientHelper.getEpisodesFormShare(book.title)) {
                if (itemT.fileName != "." && itemT.fileName != ".." &&
                    !itemT.fileName.contains("information")
                ) { // item is chapter
                    chapters.add(itemT.fileName)
                }
            }
            chapters = chapters.sortedBy { it.substringBefore('.').toInt() }
                .toCollection(ArrayList())
            bookRepository.updateChaptersById(book.id, chapters, chapters.size)
        }
    }

    private suspend fun synchronizeBooks(context: Context) {
        val localTitles = StorageManager.getAllWebtoonTitles(context)
        for (title in localTitles) {
            val book = bookRepository.getBookByTitle(title)
            if (book != null) {
                smbClientHelper.downloadWebtoon(book.title)
            }
        }
    }

    private suspend fun updateIsLocal(context: Context) {
        val dbBooks = bookRepository.getAllBooks()
        val localTitles = StorageManager.getAllWebtoonTitles(context)
        for (i in 0 until dbBooks.size) {
            if (localTitles.contains(dbBooks[i].title)) {
                bookRepository.updateIsLocal(dbBooks[i].id, 1)
            } else {
                bookRepository.updateIsLocal(dbBooks[i].id, 0)
            }
        }
    }

    private suspend fun replaceBook(replacedBook: Book, title: String) {
        bookIdPreferences.removeSpecificSharedPreference(replacedBook.title)
        val bookId = replacedBook.id
        bookRepository.updateTitleById(bookId, title)
        bookRepository.updateChaptersById(bookId, mutableListOf(), 0)
        bookRepository.updateBookmarkById(bookId, "", 0, 0)

        var isConnected = false
        try {
            isConnected = smbClientHelper.connect()
            if (isConnected) {
                val informationFile = smbClientHelper.getInformationFile(title)

                informationFile.use { smbFile ->
                    val reader = BufferedReader(InputStreamReader(smbFile.inputStream))
                    val content = reader.use { it.readText() }
                    val gson = Gson()
                    val information = gson.fromJson(content, BookInformation::class.java)
                    bookRepository.updateInformationById(bookId, information)
                }
            }

        } finally {
            if (isConnected) {
                smbClientHelper.disconnect()
            }
        }

        bookIdPreferences.saveData(title, bookId.toString())
    }

    private suspend fun missingIds(): MutableList<Int> {
        val existingIds: MutableList<Int> = mutableListOf()
        val missingIds: MutableList<Int> = mutableListOf()

        for (book in bookRepository.getAllBooks()) {
            existingIds.add(book.id)
        }

        val maxId = existingIds.maxOrNull()
        if (maxId != null) {
            for (i in 1..maxId) {
                if (!existingIds.contains(i)) {
                    missingIds.add(i)
                }
            }
        }
        return missingIds
    }
}


