import logging
import time
from typing import Optional

from msgbus import MBEasyContext, TK_PERSIST_SEQUENCER_INCREMENT, FM_PARAM, TK_SYS_NAK

from comp_exceptions import FiscalIncrementException
from persistence import Connection
from old_helper import BaseRepository
from sysactions import send_message

logger = logging.getLogger("FiscalWrapper")


class SequencerRepository(BaseRepository):
    def __init__(self, mb_context):
        # type: (MBEasyContext) -> None

        self.service_name = "FiscalPersistence"
        self.fiscal_id_name = "FiscalId"

        super(SequencerRepository, self).__init__(mb_context)

    def get_fiscal_id(self):
        # type: () -> Optional[int]

        def inner_func(connection):
            # type: (Connection) -> Optional[int]

            query = """ 
                SELECT SeqNo
                FROM Sequencer
                WHERE SeqNm = '{}'
            """.format(self.fiscal_id_name)

            cursor = connection.select(query)

            if cursor.rows() == 0:
                return None
            else:
                return int(cursor.get_row(0).get_entry(0))

        fiscal_id = self.execute_with_connection(inner_func, service_name=self.service_name)
        return fiscal_id

    def set_fiscal_id(self, fiscal_id):
        # type: (int) -> None

        def inner_func(connection):
            # type: (Connection) -> None

            query = """
                UPDATE Sequencer 
                SET SeqNo={} 
                WHERE SeqNm = '{}'
            """.format(fiscal_id, self.fiscal_id_name)
            connection.query(query)

        self.execute_with_connection(inner_func, service_name=self.service_name)

    def increment_fiscal_id(self):
        # type: () -> int

        error_msg = "Error incrementing mandatory sequence [{}] on [{}]".format(self.fiscal_id_name, self.service_name)

        for _ in range(0, 3):
            try:
                msg = send_message(self.service_name, TK_PERSIST_SEQUENCER_INCREMENT, FM_PARAM, self.fiscal_id_name)
                if msg.token == TK_SYS_NAK:
                    logger.warning(error_msg)
                    time.sleep(0.1)
                    continue

                next_fiscal_id = int(msg.data.split('\0')[0])
                return next_fiscal_id

            except Exception as ex:
                logger.warning(error_msg, ex)
                continue

        raise FiscalIncrementException(error_msg)
