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

import datetime
import logging

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

from not1mm import fsutils
from not1mm.lib.database import DataBase
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)
        uic.loadUi(fsutils.APP_DATA_PATH / "ratewindow.ui", self)
        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()
