import sqlite3
import time

from PyQt6.QtCore import QThread, pyqtSignal

from src.backend.database import Database
from src.logic.log import MyLogger
from src.logic.webrequest import BibTextTransformer, WebRequest

# from icecream import ic


class BookGrabber(QThread):
    updateSignal = pyqtSignal(int, int)

    def __init__(self, filename):
        super(BookGrabber, self).__init__(parent=None)
        self.is_Running = True
        self.logger = MyLogger("Worker")
        self.logger.log_info("Starting worker thread")
        self.data, self.app_id, self.prof_id, self.mode = self.readFile(filename)

        self.book_id = None
        time.sleep(2)

    def readFile(self, filename):
        with open(filename, "r") as file:
            data = file.readlines()
            app_id = data[0].strip()
            prof_id = data[1].strip()
            mode = data[2].strip()
            data = data[3:]
        return data, app_id, prof_id, mode

    # def resetValues(self):
    #     self.app_id = None
    #     self.prof_id = None
    #     self.mode = None
    #     self.data = None
    #     self.book_id = None

    def run(self):
        while self.is_Running:
            self.db = Database()
            item = 0
            iterdata = self.data
            print(iterdata)
            for entry in iterdata:
                signature = str(entry)
                self.logger.log_info("Processing entry: " + signature)

                webdata = WebRequest().get_ppn(entry).get_data()
                if webdata == "error":
                    continue
                bd = BibTextTransformer(self.mode).get_data(webdata).return_data()
                transformer = BibTextTransformer("RDS")
                rds = transformer.get_data(webdata).return_data("rds_availability")
                bd.signature = entry
                # confirm lock is acquired
                print("lock acquired, adding book to database")
                self.db.addBookToDatabase(bd, self.app_id, self.prof_id)
                # get latest book id
                self.book_id = self.db.getLastBookId()
                self.logger.log_info("Added book to database")
                state = 0
                print(len(rds.items))
                for rds_item in rds.items:
                    sign = rds_item.superlocation
                    loc = rds_item.location
                    # ic(sign, loc)
                    # ic(rds_item)
                    if self.app_id in sign or self.app_id in loc:
                        state = 1
                        break

                    # for book in self.books:
                    #     if book["bookdata"].signature == entry:
                    #         book_id = book["id"]
                    #         break
                self.logger.log_info(f"State of {signature}: {state}")
                print(
                    "updating availability of "
                    + str(self.book_id)
                    + " to "
                    + str(state)
                )
                try:
                    self.db.setAvailability(self.book_id, state)
                except sqlite3.OperationalError as e:
                    self.logger.log_error(f"Failed to update availability: {e}")

                # time.sleep(5)
                item += 1
                self.updateSignal.emit(item, len(self.data))
            self.logger.log_info("Worker thread finished")
            self.stop()
            if not self.is_Running:
                break

    def stop(self):
        self.is_Running = False


class AvailChecker(QThread):
    updateSignal = pyqtSignal(str, int)
    updateProgress = pyqtSignal(int, int)

    def __init__(
        self, links: list = None, appnumber: int = None, parent=None, books=list[dict]
    ):
        if links is None:
            links = []
        super().__init__(parent)
        self.logger = MyLogger("AvailChecker")
        self.logger.log_info("Starting worker thread")
        self.logger.log_info(
            "Checking availability for "
            + str(links)
            + " with appnumber "
            + str(appnumber)
            + "..."
        )
        self.links = links
        self.appnumber = appnumber
        self.books = books
        self.logger.log_info(
            f"Started worker with appnumber: {self.appnumber} and links: {self.links} and {len(self.books)} books..."
        )
        time.sleep(2)

    def run(self):
        self.db = Database()
        state = 0
        count = 0
        for link in self.links:
            self.logger.log_info("Processing entry: " + str(link))
            data = WebRequest().get_ppn(link).get_data()
            transformer = BibTextTransformer("RDS")
            rds = transformer.get_data(data).return_data("rds_availability")

            book_id = None
            for item in rds.items:
                sign = item.superlocation
                loc = item.location
                # print(item.location)
                if self.appnumber in sign or self.appnumber in loc:
                    state = 1
                    break
            for book in self.books:
                if book["bookdata"].signature == link:
                    book_id = book["id"]
                    break
            self.logger.log_info(f"State of {link}: " + str(state))
            print("Updating availability of " + str(book_id) + " to " + str(state))
            self.db.setAvailability(book_id, state)
            count += 1
            self.updateProgress.emit(count, len(self.links))
            self.updateSignal.emit(item.callnumber, state)

        self.logger.log_info("Worker thread finished")
        # teminate thread

        self.quit()


class AutoAdder(QThread):
    updateSignal = pyqtSignal(int)

    setTextSignal = pyqtSignal(int)
    progress = pyqtSignal(int)

    def __init__(self, data=None, app_id=None, prof_id=None, parent=None):
        super().__init__(parent)
        self.logger = MyLogger("AutoAdder")
        self.data = data
        self.app_id = app_id
        self.prof_id = prof_id

        print("Launched AutoAdder")
        print(self.data, self.app_id, self.prof_id)

    def run(self):
        self.db = Database()
        # show the dialog, start the thread to gather data and dynamically update progressbar and listwidget
        self.logger.log_info("Starting worker thread")
        item = 0
        for entry in self.data:
            try:
                # webdata = WebRequest().get_ppn(entry).get_data()
                # bd = BibTextTransformer("ARRAY").get_data(webdata).return_data()
                # bd.signature = entry
                self.updateSignal.emit(item)
                self.setTextSignal.emit(entry)
                # qsleep
                item += 1
                self.progress.emit(item)
                print(item, len(self.data))
                time.sleep(1)

            except Exception as e:
                print(e)
                self.logger.log_exception(
                    f"The query failed with message {e} for signature {entry}"
                )
                continue
        if item == len(self.data):
            self.logger.log_info("Worker thread finished")
            # teminate thread
            self.finished.emit()


class MockAvailCheck:
    def __init__(
        self, links: list = None, appnumber: int = None, parent=None, books=list[dict]
    ):
        if links is None:
            links = []
        super().__init__(parent)
        self.logger = MyLogger("MockAvailChecker")
        self.logger.log_info("Starting worker thread")
        self.logger.log_info(
            "Checking availability for "
            + str(links)
            + " with appnumber "
            + str(appnumber)
            + "..."
        )
        self.links = links
        self.appnumber = appnumber
        self.books = books

    def run(self):
        self.db = Database()
        state = 0
        count = 0
        result = []
        for link in self.links:
            self.logger.log_info("Processing entry: " + str(link))
            data = WebRequest().get_ppn(link).get_data()
            transformer = BibTextTransformer("RDS")
            rds = transformer.get_data(data).return_data("rds_availability")

            for item in rds.items:
                sign = item.superlocation
                loc = item.location
                # ic(item.location, item.superlocation)
                if self.appnumber in sign or self.appnumber in loc:
                    state = 1
                book_id = None
                for book in self.books:
                    if book["bookdata"].signature == link:
                        book_id = book["id"]
                        break
                self.logger.log_info(f"State of {link}: " + str(state))
                print(
                    "lock acquired, updating availability of "
                    + str(book_id)
                    + " to "
                    + str(state)
                )
                result.append((item.callnumber, state))
            count += 1
        return result

        self.logger.log_info("Worker thread finished")
        # teminate thread
