#!D:\IDE\Anaconda3\envs\Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName   : WeightModelInterface.py
@Account    : Administrator
@Time       : 2025/8/28 17:01
@Author     : xsh
@Description: 
"""
from PyQt5 import Qt
from datetime import datetime, date
import copy
from AppInterfaces.AppDBInterface import (DBManager, dbController, DBInterface)
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, asc, desc
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 AppInterfaces.utils import *
from AppSettings.utils import *

class WeightModelInterface(DBInterface, DeclarativeBase):
    ID              : int       # '数据序号　'
    conf_threshold  : float     # '置信度阀值'
    iou_threshold   : float     # '交并比阀值'
    class_cont      : float     # '筛选类别'
    iou_cont        : float     # '筛选类别'
    model_width     : int       # '图像宽度　'
    model_height    : int       # '图像高度　'
    Information     : str       # '说明信息　'
    name            : str       # '分类模型　'
    save_address    : str       # '保存路径　'

    __header__ = (
        '数据序号　',
        '置信度阀值',
        '交并比阀值',
        '筛选类别　',
        '筛选类别　',
        '图像宽度　',
        '图像高度　',
        '说明信息　',
        '分类模型　',
        '保存路径　',
    )

    __field__ = (
        'ID'            ,
        'conf_threshold',
        'iou_threshold' ,
        'class_cont'    ,
        'iou_cont'      ,
        'model_width'   ,
        'model_height'  ,
        'Information'   ,
        'name'          ,
        'save_address'  ,
    )
    __types__ = (
        int    ,
        float  ,
        float  ,
        float  ,
        float  ,
        int    ,
        int    ,
        str    ,
        str    ,
        str    ,
    )
    def isAberration(self) -> bool:
        return False if not self.has_name else self.name == 'Aberration'

    def Micronucleus(self) -> bool:
        return False if not self.has_name else self.name == 'Micronucleus'

    def isKaryotyping(self) -> bool:
        return False if not self.has_name else self.name == 'Karyotyping'

    @classmethod
    def instance(cls, **args):
        result: cls = cls.__new__(cls)
        result.__init__(**args)
        return result

    def initValue(self):
        super(WeightModelInterface, self).initValue()
        self.ID               = 1
        self.conf_threshold   = 0.5
        self.iou_threshold    = 0.45
        self.class_cont       = 0.5
        self.iou_cont         = 0.1
        self.Information      = '核型'
        self.name             = 'Karyotyping'
        self.save_address     = 'Resource/Classifier/Karyotyping_det_10X_hzh.onnx'


    @classmethod
    def Classifier(cls, name: str):
        item: cls = cls.instance()
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                try:
                    pattern: str = f'{name}%'
                    item = session.query(cls).filter(cls.name.like(pattern)).first()
                except Exception as e:
                    AppUtils.print_Exception(e)
        except Exception as EX:
            AppUtils.print_Exception(EX)
        return item
    @classmethod
    def getClassifier(cls, name: str) -> (float, float, int, int, str):
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                try:
                    pattern: str = f'{name}%'
                    item = session.query(cls).filter(cls.name.like(pattern)).first()
                except Exception as e:
                    AppUtils.print_Exception(e)
                    item = None
        except Exception as e:
            AppUtils.print_Exception(e)
            item = None
        if item is None:
            item = cls.instance()
        import sys
        root_path: str = Qt.QFileInfo(sys.argv[0]).absolutePath()
        if Qt.QFileInfo(item.save_address).isAbsolute():
            return item.conf_threshold, item.iou_threshold, item.model_width, item.model_height, item.save_address
        return item.conf_threshold, item.iou_threshold, item.model_width, item.model_height, Qt.QFileInfo(f'{root_path}/{item.save_address}').absoluteFilePath()

    @classmethod
    def getPreviewFilter(cls, level: str) -> (float, float):
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                try:
                    pattern: str = f'{level}%'
                    item = session.query(cls).filter(cls.name.like(pattern)).first()
                except Exception as e:
                    AppUtils.print_Exception(e)
                    item = None
        except Exception as e:
            AppUtils.print_Exception(e)
            item = None
        if item is None:
            return 0.5, 0.1
        return item.class_cont, item.iou_cont
    @classmethod
    def absoluteFilePath(cls, name: str) -> (float, float, int, int, str):
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                try:
                    pattern: str = f'{name}%'
                    item = session.query(cls).filter(cls.name.like(pattern)).first()
                except Exception as e:
                    AppUtils.print_Exception(e)
                    item = None
        except Exception as e:
            AppUtils.print_Exception(e)
            item = None
        if item is None:
            item = cls.instance()
        info: Qt.QFileInfo = Qt.QFileInfo(item.save_address)
        if info.isAbsolute() or info.isRoot():
            return item.conf_threshold, item.iou_threshold, item.model_width, item.model_height, item.save_address
        import sys
        root_path: str = Qt.QFileInfo(sys.argv[0]).absolutePath()
        return item.conf_threshold, item.iou_threshold, item.model_width, item.model_height, Qt.QFileInfo(f'{root_path}/{item.save_address}').absoluteFilePath()

    @classmethod
    def Classifiers(cls) -> list[str]:
        items: list[str] = []
        models: list[cls]
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                try:
                    models = session.query(cls).order_by(asc(cls.ID)).all()
                    if models is not None:
                        items.extend([item.name for item in models])
                except Exception as e:
                    AppUtils.print_Exception(e)
                session.close()

        except Exception as e:
            AppUtils.print_Exception(e)

        return items

    @classmethod
    def allClassifier(cls) -> list[dict[str, object]]:
        items: list[dict[str, object]] = []
        models: list[cls]
        item: cls
        try:
            dbController.initEngine()
            with Session(dbController.Engine) as session:
                try:
                    models = session.query(cls).all()
                    if models is not None:
                        items.extend([{
                            'Information': item.Information,
                            'name': item.name,
                        } for item in models])
                except Exception as e:
                    AppUtils.print_Exception(e)
                session.close()

        except Exception as e:
            AppUtils.print_Exception(e)

        return items

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


    @property
    def has_conf_threshold (self) -> bool:
        return hasattr(self, 'conf_threshold') and isinstance(self.conf_threshold, float   )


    @property
    def has_iou_threshold  (self) -> bool:
        return hasattr(self, 'iou_threshold' ) and isinstance(self.iou_threshold , float   )


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


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


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

    @property
    def has_model_width  (self) -> bool:
        return hasattr(self, 'model_width' ) and isinstance(self.model_width , (int, float))

    @property
    def has_model_height (self) -> bool:
        return hasattr(self, 'model_height') and isinstance(self.model_height, (int, float))