from datetime import datetime
from sqlalchemy import Boolean, Column, DateTime, Integer, String, select
from db import Base, CRUD
import utils


class Practitioner(Base):
    __tablename__ = "practitioners"

    id = Column(Integer, primary_key=True, index=True)
    familyName = Column(String)
    givenName = Column(String)
    middleName = Column(String)
    userIdLpu = Column(String, unique=True)
    name = Column(String)
    fullName = Column(String)
    esiaAuth = Column(Boolean)
    attorney = Column(String, nullable=True)
    expired_at = Column(DateTime)
    created_at = Column(DateTime, default=datetime.now)
    updated_at = Column(DateTime, default=datetime.now, onupdate=datetime.now)

    def __init__(self, **kwargs):
        for key, value in kwargs.items():
            setattr(self, key, value)

    def toDict(self):
        return utils.toDict(self)

    async def save(self) -> "Practitioner":
        return await CRUD.create(self, refresh=True)

    async def edit(self, **kwargs) -> "Practitioner":
        return await CRUD.update(Practitioner, self.id, **kwargs)

    async def delete(self) -> bool:
        return await CRUD.delete(self)

    @staticmethod
    async def addPractitioner(**kwargs):
        userIdLpu = kwargs.get("userIdLpu", None)
        if not userIdLpu:
            utils.logger.error("Не указан идентификатор сотрудника")
            return utils.answer(
                success=False, message="Не указан идентификатор сотрудника"
            )
        practitioner = await Practitioner.getPractitionerByIdLpu(userIdLpu, False, True)
        if practitioner.success:
            utils.logger.error(
                f"Сотрудник {practitioner.data.name} с идентификатором {userIdLpu} уже существует"
            )
            return utils.answer(
                success=False,
                message=f"Сотрудник {practitioner.data.name} с идентификатором {userIdLpu} уже существует",
            )
        kwargs["name"] = (
            f"{kwargs.get('familyName', '')} {kwargs.get('givenName', ' ')[:1]}. {kwargs.get('middleName', ' ')[:1]}."
        )
        kwargs["fullName"] = (
            f"{kwargs.get('familyName', '')} {kwargs.get('givenName', '')} {kwargs.get('middleName', '')}"
        )
        utils.logger.info(
            f"Добавление сотрудника {kwargs.get('name', '')} с идентификатором {userIdLpu}"
        )
        practitioner = Practitioner(**kwargs)
        data = await practitioner.save()
        return utils.answer(data=data)

    @staticmethod
    async def getPractitioners(toDict: bool = True):
        practitioners = await CRUD.read(select(Practitioner), all=True)
        data = (
            [practitioner.toDict() for practitioner in practitioners]
            if toDict
            else practitioners
        )
        return utils.answer(data=data)

    @staticmethod
    async def getPractitionerByIdLpu(
        idLpu: str, toDict: bool = True, isCheck: bool = False
    ):
        if type(idLpu) != str:
            idLpu = str(idLpu)
        practitioner = await CRUD.read(
            select(Practitioner).where(Practitioner.userIdLpu == idLpu)
        )
        if practitioner:
            data = practitioner.toDict() if toDict else practitioner
            return utils.answer(data=data)

        if not isCheck:
            utils.logger.error(f"Сотрудник не найден, idLpu: {idLpu}")
        return utils.answer(success=False, message="Сотрудник не найден")

    @staticmethod
    async def editPractitionerByIdLpu(idLpu: str, **kwargs):
        practitioner = await Practitioner.getPractitionerByIdLpu(idLpu, False)
        if not practitioner.success:
            utils.logger.error(f"Сотрудник не найден, idLpu: {idLpu}")
            return utils.answer(success=False, message="Сотрудник не найден")
        data = await practitioner.data.edit(**kwargs)
        return utils.answer(data=data)

    @staticmethod
    async def deletePractitionerByIdLpu(idLpu: str) -> bool:
        try:
            practitioner = await Practitioner.getPractitionerByIdLpu(idLpu, False)
            esiaAuth = practitioner.data.esiaAuth
            await practitioner.data.delete()
            utils.logger.info(f"Сотрудник удален, idLpu: {idLpu}")
            return utils.answer(data=esiaAuth)
        except:
            utils.logger.error(f"Сотрудник не удален, idLpu: {idLpu}")
            return utils.answer(success=False, message="Сотрудник не удален")
