# encoding: utf-8
import json
from datetime import (
    datetime,
    timedelta
)

from msgbus import MBEasyContext
from old_helper import BaseRepository
from persistence import Connection
from typing import (
    List,
    Dict
)

from tefcancellationreport.model import (
    TefTender,
    CardBrand
)

CARD_BRANDS_CACHE = None


class OrderRepository(BaseRepository):

    def __init__(
        self,
        mb_context,     # type: MBEasyContext
        pos_list        # type: List
    ):
        # type: (...) -> None

        super(
            OrderRepository,
            self
        ).__init__(mb_context)

        self.pos_list = pos_list

    def get_tef_tenders_by_pos(
        self,
        initial_date,   # type: datetime
        end_date        # type: datetime
    ):
        # type: (...) -> List[TefTender]

        def inner_func(
            conn    # type: Connection
        ):
            # type: (...)->List

            query = self._OrdersQuery.format(initial_date, end_date)
            tenders = {}
            for row in conn.select(query):
                tender_detail = json.loads(row.get_entry("TenderDetail"))
                receipt_cancel = tender_detail.get("ReceiptCancel")
                if receipt_cancel is not None:
                    if receipt_cancel.get("NsuHost") is not None:
                        continue

                date = row.get_entry("Timestamp")[:10]
                tef_tender = TefTender(
                    row_database=row,
                    tender_detail=tender_detail
                )
                if date in tenders:
                    tenders[date].append(tef_tender)
                else:
                    tenders[date] = [tef_tender]

            return [tenders]

        return self.execute_parallel_in_all_databases_returning_flat_list(inner_func, self.pos_list)

    def get_card_brands(self):
        # type: () -> Dict[int, CardBrand]

        global CARD_BRANDS_CACHE

        def inner_func(
            conn    # type: Connection
        ):
            # type: (...) -> Dict[int, CardBrand]

            query = self._CardBrandsQuery
            card_brands = {}
            for row in conn.select(query):
                card_brands[int(row.get_entry(0))] = CardBrand(row_database=row)

            return card_brands

        if not CARD_BRANDS_CACHE:
            CARD_BRANDS_CACHE = self.execute_with_connection(
                inner_func,
                service_name="FiscalPersistence"
            )

        return CARD_BRANDS_CACHE

    @staticmethod
    def _format_date(
        date    # type: datetime
    ):
        # type: (...) -> str

        return date.strftime("%Y-%m-%dT%H:%M:%S.%f")

    _OrdersQuery = """
                    SELECT
                        TT.TenderDescr,
                        OT.Timestamp,
                        OT.TenderAmount,
                        OT.TenderDetail
                    FROM TenderElectronicType AS TET
                    JOIN TenderType AS TT
                        ON TT.ElectronicType=TET.TypeId
                    JOIN OrderTender AS OT
                        ON OT.TenderId=TT.TenderId
                    JOIN Orders AS O
                        ON O.OrderId=OT.OrderId
                    WHERE TET.TypeId
                        NOT IN (CAST(0 AS INTEGER), CAST(9 AS INTEGER))
                        AND OT.TenderAmount=CAST(0 AS FLOAT)
                        AND O.BusinessPeriod BETWEEN '{0}' AND '{1}'
                    ORDER BY OT.Timestamp DESC
                  """

    _CardBrandsQuery = """
                    SELECT Bandeira, Descricao
                    FROM fiscal.BandeiraCartao
                  """
