#!D:\IDE\Anaconda3\envs\Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
 @Author: Administrator
 @FileName: UserModel.py
 @DateTime: 2025/6/22 20:36
 @SoftWare: PyCharm
 @Author  ：xsh
"""

from PyQt5 import Qt
from datetime import datetime, date
import copy
from AppCore.AppDBModels.CoreModel import (CoreModel, DBManager, dbController)
from sqlalchemy.orm import declarative_base, mapper, sessionmaker, Session
from sqlalchemy.orm import (declarative_base, Mapped, mapped_column, relationship, mapper, sessionmaker)
from sqlalchemy import Table, Engine, create_engine, Column, ForeignKey, and_, or_, insert, delete, update, select, func, ColumnElement,distinct
from sqlalchemy.types import (Text, VARCHAR, REAL, Float, Integer, String, SmallInteger, DateTime, Date, ARRAY,Boolean, JSON)
from sqlalchemy.orm.decl_api import DeclarativeBase, MetaData
from AppUtils.utils import *
from AppCore.Levels import *
from AppSettings.Settings import RECODE_FAILURE, RECODE_SUCCEED, RECODE_WARNING
from AppCore.AppDBModels.Permissions.RoleModel import RoleModel
from AppCore.AppDBModels.Permissions.GroupModel import GroupModel
class UserModel(CoreModel):
    __tablename__ = 't_UserModel'
    ID          : Mapped[int            ] = mapped_column(primary_key=True                          , nullable=False)
    IS_ACTIVE   : Mapped[int            ] = mapped_column(default=0                                 , nullable=True )
    IS_LOGIN    : Mapped[int            ] = mapped_column(default=0                                 , nullable=True )
    Role_ID     : Mapped[int            ] = mapped_column(ForeignKey("t_RoleModel.ID"  ), default=1 , nullable=True )
    GROUP_ID    : Mapped[int            ] = mapped_column(ForeignKey("t_GroupModel.ID" ), default=1 , nullable=True )
    PASSWORD    : Mapped[str            ] = mapped_column(Text                                      , nullable=True )
    USERNAME    : Mapped[str            ] = mapped_column(Text                                      , nullable=True )
    role        : Mapped['RoleModel'    ] = relationship("RoleModel" , backref="t_UserModel" , foreign_keys=[Role_ID ])
    group       : Mapped['GroupModel'   ] = relationship("GroupModel", backref="t_GroupModel", foreign_keys=[GROUP_ID])
    def __init__(self, **args):
        super(UserModel, self).__init__()
        self.initialize()
        self.initParameter(**args)

    def serialize(self) -> dict[str, object]:
        buffer: dict[str, object] = super(UserModel, self).serialize()
        buffer['role'] = self.role.DICT_DATA if self.has_role else {}
        return buffer

    def deserialize(self, buffer: dict[str, object]):
        super(UserModel, self).deserialize(buffer)
        self.init_role()
        self.role.deserialize(buffer.get('role', {}))


    @classmethod
    def initModels(cls):
        return [
            cls.instance(ID=1, IS_ACTIVE=1, PARENT_ID=3, Role_ID=1, PASSWORD=AppConvert.toMD5('admin')      , USERNAME='admin'      ),
            cls.instance(ID=2, IS_ACTIVE=1, PARENT_ID=3, Role_ID=2, PASSWORD=AppConvert.toMD5('admin123456'), USERNAME='admin123456'),
            cls.instance(ID=3, IS_ACTIVE=1, PARENT_ID=2, Role_ID=3, PASSWORD=AppConvert.toMD5('user')       , USERNAME='user'       ),
        ]

    def initUserModels(self):
        item1: UserModel = UserModel(ID=1, IS_ACTIVE=1, PARENT_ID=3, Role_ID=1, PASSWORD=AppConvert.toMD5('admin')      , USERNAME='admin'      )
        item2: UserModel = UserModel(ID=2, IS_ACTIVE=1, PARENT_ID=3, Role_ID=2, PASSWORD=AppConvert.toMD5('admin123456'), USERNAME='admin123456')
        item3: UserModel = UserModel(ID=3, IS_ACTIVE=1, PARENT_ID=2, Role_ID=3, PASSWORD=AppConvert.toMD5('user')       , USERNAME='user'       )
        item1.init_role(IS_ACTIVE=1,  LAST_LOGIN=datetime.now(), DATE_JOINED=datetime.now(), ROLENAME='默认管理员')
        item2.init_role(IS_ACTIVE=1,  LAST_LOGIN=datetime.now(), DATE_JOINED=datetime.now(), ROLENAME='管理员'  )
        item3.init_role(IS_ACTIVE=1,  LAST_LOGIN=datetime.now(), DATE_JOINED=datetime.now(), ROLENAME='用户'   )

        items: list[UserModel] = [
            item1,
            item2,
            item3,
        ]
        return items
    @classmethod
    def getCurrentUser(cls) -> 'UserModel':
        item: cls = None
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                item = session.query(cls).filter(or_(cls.IS_LOGIN != 0, cls.IS_ACTIVE != 0)).order_by(cls.ID.desc()).first()
                session.close()
        except Exception as e:
            AppUtils.print_Exception(e)
        return item

    @classmethod
    def sign_in_Plaintext(cls, username: str, password: str) -> int:
        isWrong: int = RECODE_FAILURE
        item: cls
        _password: str = AppConvert.toMD5(password)
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                item = session.query(cls).filter(cls.USERNAME == username).first()
                if item is not None:
                    isWrong = RECODE_SUCCEED if item.PASSWORD == _password else RECODE_FAILURE
                    if RECODE_SUCCEED == isWrong:
                        session.query(cls).filter(cls.USERNAME == username, cls.PASSWORD == _password).update({cls.IS_LOGIN: 1, cls.IS_ACTIVE: 1})
                        session.commit()
                session.close()
        except Exception as e:

            AppUtils.print_Exception(e)
        return isWrong
    @classmethod
    def login(cls, username: str, password: str) -> int:
        isWrong: int = RECODE_FAILURE
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                item = session.query(cls).filter(cls.USERNAME == username).first()
                if item is not None:
                    isWrong = RECODE_SUCCEED if item.PASSWORD == password else RECODE_FAILURE
                    if RECODE_SUCCEED == isWrong:
                        session.query(cls).filter(cls.USERNAME == username, cls.PASSWORD == password).update({cls.IS_LOGIN: 1, cls.IS_ACTIVE: 1})
                        session.commit()
                session.close()
        except Exception as e:

            AppUtils.print_Exception(e)
        return isWrong

    @classmethod
    def sign_in(cls, username: str, password: str) -> int:
        isWrong: int = RECODE_FAILURE
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                item = session.query(cls).filter(cls.USERNAME == username).first()
                if item is not None:
                    isWrong = RECODE_SUCCEED if item.PASSWORD == password else RECODE_FAILURE
                    if RECODE_SUCCEED == isWrong:
                        session.query(cls).filter(cls.USERNAME == username, cls.PASSWORD == password).update({cls.IS_LOGIN: 1, cls.IS_ACTIVE: 1})
                        session.commit()
                session.close()
        except Exception as e:

            AppUtils.print_Exception(e)
        return isWrong

    @classmethod
    def sign_out(cls, username: str) -> int:
        isWrong: int = RECODE_FAILURE
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                session.query(cls).filter(cls.USERNAME == username).update({cls.IS_LOGIN: 0, cls.IS_ACTIVE: 0})
                session.commit()
                session.close()
        except Exception as e:

            AppUtils.print_Exception(e)
        return isWrong

    @classmethod
    def sign_out_id(cls, user_id: int) -> int:
        isWrong: int = RECODE_FAILURE
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                session.query(cls).filter(cls.ID == user_id).update({cls.IS_LOGIN: 0, cls.IS_ACTIVE: 0})
                session.commit()
                session.close()
        except Exception as e:

            AppUtils.print_Exception(e)
        return isWrong


    @property
    def has_ID        (self) -> bool:
        return hasattr(self, 'ID'         ) and isinstance(self.ID       , int       )

    @property
    def has_IS_ACTIVE (self) -> bool:
        return hasattr(self, 'IS_ACTIVE'  ) and isinstance(self.IS_ACTIVE, int       )

    @property
    def has_PARENT_ID (self) -> bool:
        return hasattr(self, 'PARENT_ID'  ) and isinstance(self.PARENT_ID, int       )

    @property
    def has_Role_ID   (self) -> bool:
        return hasattr(self, 'Role_ID'    ) and isinstance(self.Role_ID  , int       )

    @property
    def has_PASSWORD  (self) -> bool:
        return hasattr(self, 'PASSWORD'   ) and isinstance(self.PASSWORD , str       )

    @property
    def has_USERNAME  (self) -> bool:
        return hasattr(self, 'USERNAME'   ) and isinstance(self.USERNAME , str       )

    @property
    def has_parent    (self) -> bool:
        return hasattr(self, 'parent'     ) and isinstance(self.parent   , GroupModel)

    @property
    def has_role      (self) -> bool:
        return hasattr(self, 'role'       ) and isinstance(self.role     , RoleModel      )

    def init_role   (self, **args):
        if not self.has_role  :
            self.role   = RoleModel(**args)
        else:
            self.role.ID=self.Role_ID if self.has_Role_ID else None
            self.role.initParameter(**args)

    def initValue(self):
        super(UserModel, self).initValue()

    __field__ = (
        'ID'         ,
        'IS_ACTIVE'  ,
        'IS_LOGIN'   ,
        'Role_ID'    ,
        'GROUP_ID'   ,
        'PASSWORD'   ,
        'USERNAME'   ,
    )

    __types__ = (
        int        ,
        int        ,
        int        ,
        int        ,
        int        ,
        str        ,
        str        ,
    )