"""
not1mm Contest logger
Email: michael.bridak@gmail.com
GPL V3
Class: RateWindow
Purpose: not sure yet
"""

import datetime
import logging

from PyQt6.QtCore import QTimer, pyqtSignal
from PyQt6.QtWidgets import QDockWidget

from not1mm import fsutils
from not1mm.lib.database import DataBase
from not1mm.lib.i18n import load_ui
from not1mm.lib.preferences import Preferences

logger = logging.getLogger(__name__)


class RateWindow(QDockWidget):
    """The rate window. Shows something important."""

    message = pyqtSignal(dict)
    dbname = None
    pref = {}  # noqa: RUF012
    poll_time = datetime.datetime.now(datetime.UTC) + datetime.timedelta(
        milliseconds=1000
    )
    ratewindow_closed = pyqtSignal()

    def __init__(self, action):
        super().__init__()
        self.action = action
        self.active = False
        self.load_pref()
        self.dbname = fsutils.USER_DATA_PATH / self.pref.get(
            "current_database", "ham.db"
        )
        self.database = DataBase(self.dbname, fsutils.APP_DATA_PATH)
        self.database.current_contest = self.pref.get("contest", 0)
        load_ui(self, fsutils.APP_DATA_PATH / "ratewindow.ui")
        self.timer = QTimer()
        self.timer.timeout.connect(self.get_run_and_total_qs)
        self.timer.start(10000)

    def msg_from_main(self, packet):
        """Process messages from the main window."""

        if packet.get("cmd", "") == "NEWDB":
            self.load_pref()
            self.dbname = fsutils.USER_DATA_PATH / self.pref.get(
                "current_database", "ham.db"
            )
            self.database = DataBase(self.dbname, fsutils.APP_DATA_PATH)
            self.database.current_contest = self.pref.get("contest", 0)
        if packet.get("cmd", "") in ("CONTACTCHANGED", "UPDATELOG", "DELETE"):
            self.get_run_and_total_qs()

    def setActive(self, mode: bool):
        self.active = bool(mode)

    def load_pref(self) -> None:
        """
        Load preference file to get current db filename and sets the initial darkmode state.

        Parameters
        ----------
        None

        Returns
        -------
        None
        """
        self.pref = Preferences.data()

    def get_run_and_total_qs(self):
        """get numbers"""

        if not self.active or not self.isVisible():
            return
        # Get Q's in the 60 Minutes
        query = f"select (julianday(MAX(ts)) -  julianday(MIN(ts))) * 24 * 60 as timespan, count(*) as items from (select * from dxlog where ContestNR = {self.database.current_contest} and datetime(TS) > datetime(current_timestamp, '-60 minutes'));"
        result = self.database.exec_sql(query)
        if result.get("items", 0) < 1:
            self.last_hour.setText("--- Q/h")
        elif result.get("items", 0) == 1:
            self.last_hour.setText("1 Q/h")
        else:
            try:
                perhour = (60.0 / result.get("timespan", 60)) * result.get("items", 0)
                self.last_hour.setText(str(f"{perhour:.2f} Q/h"))
            except (ZeroDivisionError, TypeError):
                ...

        # Get Q's per hour rate of the last 10 QSO's
        query = f"SELECT (julianday(MAX(ts)) -  julianday(MIN(ts))) * 24 * 60 as timespan, count(*) as items FROM ( select * from DXLOG where ContestNR = {self.database.current_contest} ORDER by ts DESC limit 10);"
        result = self.database.exec_sql(query)
        if result.get("items", 0) < 10:
            self.ten_last_qso.setText("--- Q/h")
        else:
            try:
                perhour = (60.0 / result.get("timespan", 60)) * result.get("items", 0)
                self.ten_last_qso.setText(str(f"{perhour:.2f} Q/h"))
            except (ZeroDivisionError, TypeError):
                ...

        # Get Q's per hour rate of the last 100 QSO's
        query = f"SELECT (julianday(MAX(ts)) -  julianday(MIN(ts))) * 24 * 60 as timespan, count(*) as items FROM (select * from DXLOG where ContestNR = {self.database.current_contest} ORDER by ts DESC limit 100);"
        result = self.database.exec_sql(query)
        if result.get("items", 0) < 100:
            self.hundred_last_qso.setText("--- Q/h")
        else:
            try:
                perhour = (60.0 / result.get("timespan", 60)) * result.get("items", 0)
                self.hundred_last_qso.setText(str(f"{perhour:.2f} Q/h"))
            except (ZeroDivisionError, TypeError):
                ...

        # Get rate for the current hour
        query = f"SELECT strftime('%Y-%m-%d %H:00:00','now') as limit_stamp, strftime('%H00','now') as current_hour, count(*) as items FROM DXLOG where ContestNR = {self.database.current_contest} and datetime(TS) > limit_stamp;"
        result = self.database.exec_sql(query)

        self.since_lasthour_label.setText(
            f"Since {result.get('current_hour', '0000')}z:"
        )
        self.since_lasthour.setText(f"{result.get('items', '0')} QSO")

        # Get Run QSO's and S&P QSO's
        query = f"select sum(IsRunQSO) as runs, count(*) as totalqs from dxlog where ContestNR = {self.database.current_contest};"
        result = self.database.exec_sql(query)
        if result.get("runs") is None:
            result["runs"] = 0
        try:
            sandp = result.get("totalqs", 0) - result.get("runs", 0)
            self.run_qso.setText(f"{result.get('runs', 0)}")
            self.sandp_qso.setText(f"{sandp}")
        except TypeError:
            ...

        # Get runs for the current hour
        query = f"SELECT strftime('%Y-%m-%d %H:00:00','now') as limit_stamp, sum(IsRunQSO) as runs, count(*) as totalqs FROM DXLOG where ContestNR = {self.database.current_contest} and datetime(TS) > limit_stamp;"
        result = self.database.exec_sql(query)
        if result.get("runs") is None:
            result["runs"] = 0
        try:
            sandp = result.get("totalqs", 0) - result.get("runs", 0)
            self.hour_run_qso.setText(f"{result.get('runs', 0)}")
            self.hour_sandp_qso.setText(f"{sandp}")
        except TypeError:
            ...

    def closeEvent(self, event) -> None:
        self.action.setChecked(False)
        self.ratewindow_closed.emit()
        event.accept()
