from datetime import date
from logging import getLogger
from typing import Literal

from fastapi import status as st
from httpx import AsyncClient

from core.config import settings
from shared import exceptions as e
from shared.functions import clean_params
from shared.redis import client as cache

from . import schema as s


class TMK_API(AsyncClient):
    def __init__(self):
        self.logger = getLogger(__name__)
        super().__init__(base_url=settings.TMK_BASE_URL, verify=False)

    async def get_token(self):
        token = await cache.get('tmk_token')

        if token is None:
            token = await self.login()
            await cache.set('tmk_token', token, 10800)

        else:
            token = token.decode()

        return token

    async def login(self):
        req = await self.post(
            '/auth',
            json={
                'login': settings.TMK_LOGIN,
                'password': settings.TMK_PASSWORD,
            },
        )

        match req.status_code:
            case st.HTTP_200_OK:
                return s.AccessTokenModel.model_validate(
                    req.json()
                ).access_token

            case _:
                self.logger.error(req.json())
                raise e.UnknownException

    async def getQueue(
        self,
        code_mo: str | None = None,
        doctor_spec: str | None = None,
        doctor_snils: str | None = None,
        doctor_snils_strict: Literal['y', 'n'] = 'n',
        date_begin: date | None = None,
        date_end: date | None = None,
        patient_snils: str | None = None,
        patient_fio: str | None = None,
        patient_policy: str | None = None,
        patient_phone: str | None = None,
        patient_birthdate: date | None = None,
        tk_status: str | None = None,
    ):
        token = await self.get_token()
        req = await self.get(
            '/getQueue',
            headers={'Authorization': f'Bearer {token}'},
            params=clean_params(
                {
                    'code_mo': code_mo,
                    'doctor_spec': doctor_spec,
                    'doctor_snils': doctor_snils,
                    'doctor_snils_strict': doctor_snils_strict,
                    'date_begin': date_begin,
                    'date_end': date_end,
                    'patient_snils': patient_snils,
                    'patient_fio': patient_fio,
                    'patient_policy': patient_policy,
                    'patient_phone': patient_phone,
                    'patient_birthdate': patient_birthdate,
                    'tk_status': tk_status,
                }
            ),
        )

        match req.status_code:
            case st.HTTP_200_OK:
                return [s.QueueModel.model_validate(i) for i in req.json()]

            case _:
                self.logger.error(req.json())
                raise e.UnknownException

    async def getInfo(self, guid: str):
        token = await self.get_token()
        req = await self.get(
            '/getTMKInfo',
            headers={'Authorization': f'Bearer {token}'},
            params={'guid': guid},
        )

        match req.status_code:
            case st.HTTP_200_OK:
                return s.QueueModel.model_validate(req.json())

            case _:
                self.logger.error(req.json())
                raise e.UnknownException
