from threading import Lock
from typing import List

from msgbus import MBEasyContext
from mwhelper import BaseRepository
from persistence import Connection

from dailygoals_services.model import SaleChallenge
from dailygoals_services.model import GetSalesChallengeException, InsertSalesChallengeException, \
    DeleteSalesChallengeException, UpdateSalesChallengeException
from dailygoals_services.model.repository import DailyGoalsRepository as DailyGoalsServicesRepository


class DailyGoalsRepository(DailyGoalsServicesRepository, BaseRepository):

    def __init__(self, mb_context, persistence_name, database_lock):
        # type: (MBEasyContext, str, Lock) -> None

        super(DailyGoalsRepository, self).__init__(mb_context)

        self.persistence_name = persistence_name
        self.database_lock = database_lock

    def get_sales_challenge(self, limit=None):
        # type: (int) -> List[SaleChallenge]

        limit = limit if limit else 5
        try:
            def inner_func(conn):
                # type: (Connection) -> List[SaleChallenge]

                query = """
                            SELECT Id, Name, StartDate, EndDate, Products, CreatedBy
                            FROM SalesChallenge
                            ORDER BY StartDate DESC, EndDate DESC
                            LIMIT {}
                        """
                query_format = query.format(limit)
                cursor = conn.select(query_format)
                sales_challenge = []

                for row in cursor:
                    products = row.get_entry("Products") or "[]"
                    challenge = SaleChallenge(
                        name=row.get_entry("Name").decode("utf-8"),
                        start_date=row.get_entry("StartDate").decode(),
                        end_date=row.get_entry("EndDate").decode(),
                        products=products,
                        created_by=row.get_entry("CreatedBy"),
                        challenge_id=int(row.get_entry("Id")),
                    )
                    sales_challenge.append(challenge)
                return sales_challenge

            return self.execute_with_connection(inner_func, service_name=self.persistence_name)
        except (Exception,):
            raise GetSalesChallengeException()

    def insert_sales_challenge(self, challenge):
        # type: (SaleChallenge) -> int

        try:
            def inner_func(conn):
                # type: (Connection) -> None

                query = """
                            INSERT INTO SalesChallenge(
                                Name, StartDate, EndDate, Products, CreatedBy
                            )
                            VALUES ('{}', '{}', '{}', '{}', '{}')
                        """
                query_format = query.format(
                    challenge.name.encode("utf-8"),
                    challenge.start_date.encode(),
                    challenge.end_date.encode(),
                    challenge.products,
                    challenge.created_by,
                )
                return conn.query(query_format)

            return self.execute_with_connection(inner_func, service_name=self.persistence_name)
        except (Exception,):
            raise InsertSalesChallengeException()

    def delete_sales_challenge(self, sale_challenge_id):
        # type: (int) -> int

        try:
            def inner_func(conn):
                # type: (Connection) -> None

                query = """
                            DELETE FROM SalesChallenge
                            WHERE Id={}
                        """
                query_format = query.format(sale_challenge_id)
                return conn.query(query_format)

            return self.execute_with_connection(inner_func, service_name=self.persistence_name)
        except (Exception,):
            raise DeleteSalesChallengeException()

    def update_sales_challenge(self, challenge):
        # type: (SaleChallenge) -> int

        try:
            def inner_func(conn):
                # type: (Connection) -> None

                query = """
                            UPDATE SalesChallenge
                            SET Name='{}', StartDate='{}', EndDate='{}', Products='{}', CreatedBy={}
                            WHERE Id={}
                        """
                query_format = query.format(
                    challenge.name.encode("utf-8"),
                    challenge.start_date.encode(),
                    challenge.end_date.encode(),
                    challenge.products,
                    challenge.created_by,
                    challenge.challenge_id,
                )
                return conn.query(query_format)

            return self.execute_with_connection(inner_func, service_name=self.persistence_name)
        except (Exception,):
            raise UpdateSalesChallengeException()
