#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：DBFrame.py
@Description：
@Author：XSH
@Time：2025/12/24 8:54
@Department：研发部
@Copyright：©2025 乐辰生物
"""
from PyQt5                                  import Qt                       #
from AppSettings.Settings                   import SIGNAL_CONNECTION_TYPE   #
from AppCore.Levels                         import *                        #
from AppCore.DBModels                       import *                        #
from AppUtils.UiUtils                       import UiUtils                  #
from AppUtils.utils                         import *                        #
from AppInterfaces.UiInterface              import UiInterface              #
from AppHeadEnd.DBModelViews.ActionMenuBar  import ActionMenuBar            #

class DBFrame(Qt.QTableWidget, UiInterface):
    ActionMoveSignal: Qt.pyqtSignal = Qt.pyqtSignal(object)
    Model       : DBInterface                   #
    Menus       : ActionMenuBar                 #
    IsAction    : bool                          #
    Models      : list[DBInterface]             #

    def __init__(self, model: DBInterface = None, isAction: bool = False, info='', parent: Qt.QWidget = None):
        super(DBFrame, self).__init__(parent)
        self.Model       = model
        self.IsAction    = isAction
        self.Initialization("表格编辑" if not isinstance(info, str) or len(info) <= 0 else f'{info}',  self, parent)
        self.initWindowIcon()
        self.initWidgetStyle()

    def initConnect(self):
        super(DBFrame, self).initConnect()
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        self.Menus.ActionSignal.connect(self.SlotActionSignal, TYPE)
        self.model().dataChanged.connect(self.SlotDataChanged, TYPE)

    def show(self) -> None:
        self.flushItems()
        return super(DBFrame, self).show()
    def SlotDataChanged(self, topLeft: Qt.QModelIndex, bottomRight: Qt.QModelIndex, roles, p_int=None, *args, **kwargs):
        print("DataChanged", topLeft, bottomRight, roles)
        if topLeft.isValid():
            self.updateRowItem(topLeft.row())
        if bottomRight.isValid():
            self.updateRowItem(bottomRight.row())


    def SlotActionSignal(self, name: str):
        if name == '　　刷新　　':
            self.clearItems()
            self.initModels()
        elif name == '　　移动　　':
            item: Qt.QTableWidgetItem = self.currentItem()
            if not isinstance(item, Qt.QTableWidgetItem):
                return
            model: DBInterface = item.data(Qt.Qt.UserRole)
            if not isinstance(model, DBInterface):
                return
            self.ActionMoveSignal.emit(model.instance(**model.to_field(True)))

        elif name == '　　删除　　':
            self.removeRowItem(self.currentRow())

    def initWidgetStyle(self):
        self.setStyleSheet(UiUtils.getTableStyle())


    def mouseReleaseEvent(self, ev: Qt.QMouseEvent) -> None:
        if ev.button() == Qt.Qt.RightButton:
            self.initMenus()
            self.Menus.draw(ev.globalPos())
            ev.accept()

        return super(DBFrame, self).mouseReleaseEvent(ev)

    def initValue(self):
        super(DBFrame, self).initValue()
        self.initMenus  ()
        self.initModels ()


    def initProperty(self):
        super(DBFrame, self).initProperty()

        self.setAlternatingRowColors(False)  # 禁用隔行变色
        self.setShowGrid(True)  # Show grid lines
        self.verticalHeader().setVisible(False)  # Hide row numbers
        self.verticalHeader().setDefaultSectionSize(40)
        self.initHorizontalHeader()
        self.setMinimumWidth(800)
        self.setMinimumHeight(200)

    def initHorizontalHeader(self):
        header: list[str] = []
        if self.hasModel:
            header = list(self.Model.__field__)
        colCount: int = len(header)
        self.setHorizontalHeaderLabels(header)
        self.setColumnCount(colCount)
        self.horizontalHeader().setSectionResizeMode(Qt.QHeaderView.Custom)
        for index, _property in enumerate(header):
            if index == 0:
                self.setColumnWidth(index, 50)
            else:
                self.setColumnWidth(index, 180)
        self.setSelectionBehavior(Qt.QTableWidget.SelectRows)  # Select entire rows
        self.setSelectionMode(Qt.QTableWidget.SingleSelection)  # Single row selection
        self.setEditTriggers(Qt.QTableWidget.CurrentChanged)  # Read-only
        self.horizontalHeader().setStretchLastSection(True)  # Stretch last column
        self.horizontalHeader().setSectionResizeMode(Qt.QHeaderView.Interactive)
        pass

    def initMenus       (self):
        if not self.hasMenus       :
            if self.isAction:
                self.Menus = ActionMenuBar(['　　刷新　　', '　　移动　　', '　　删除　　'])
            else:
                self.Menus = ActionMenuBar(['　　刷新　　', '　　删除　　'])


    def initIsAction    (self):
        if not self.hasIsAction    :
            self.IsAction     = False

    def initModels      (self):
        if not self.hasModels      :
            self.Models       = []
        if len(self.Models) <= 0:
            if self.hasModel:
                self.Models = self.Model.all()

        self.flushItems()

    def clearItems(self):
        self.model().blockSignals(True)
        self.clearContents()
        if self.hasModels:
            while len(self.Models) > 0:
                self.Models.pop()
            self.Models.clear()
        self.model().blockSignals(False)

    def flushItems(self):
        self.model().blockSignals(True)
        self.clearContents()
        self.initHorizontalHeader()
        self.model().blockSignals(False)
        if not self.hasModels or not self.hasModel:
            return
        if self.isEmpty:
            return

        self.model().blockSignals(True)
        for row, model in enumerate(self.Models):
            self.insertRowItem(row, model, False)
        self.setCurrentItem(None)
        self.viewport().update()
        self.model().blockSignals(False)


    def insertRowItem(self, row: int, model: DBInterface, isBlock: bool =  True):
        if not isinstance(model, DBInterface):
            return
        if isBlock:
            self.model().blockSignals(True)
        field: list[str]  = self.Model.__field__
        types: list[type] = self.Model.__types__
        value: object
        self.insertRow(row)
        for col, _property in enumerate(field):
            item = Qt.QTableWidgetItem()

            value = AppConvert.ObjectConvert(getattr(model, _property,  None), types[col])
            item.setData(Qt.Qt.DisplayRole, value)
            item.setData(Qt.Qt.ToolTipRole, f'{_property}  {types[col]}')
            item.setData(Qt.Qt.UserRole, model)
            self.setItemField(item, model,  _property)
            self.setItem(row, col, item)
        if isBlock:
            self.model().blockSignals(False)


    def removeRowItem(self, row: int):
        if row < 0:
            return
        item: Qt.QTableWidgetItem = self.item(row, 0)
        if not isinstance(item, Qt.QTableWidgetItem):
            return
        model: DBInterface = item.data(Qt.Qt.UserRole)
        self.model().blockSignals(True)
        self.removeRow(row)
        if isinstance(model, DBInterface):
            self.Models.remove(model)
            model.delete()
        self.model().blockSignals(False)

    def updateRowItem(self, row: int):
        item: Qt.QTableWidgetItem = self.item(row, 0)
        if not isinstance(item, Qt.QTableWidgetItem):
            return
        model: DBInterface = item.data(Qt.Qt.UserRole)
        if not isinstance(model, DBInterface):
            return
        field: list[str]  = model.__field__
        types: list[type] = model.__types__
        for col, field in enumerate(field):
            item = self.item(row, col)
            if not isinstance(item, Qt.QTableWidgetItem):
                continue
            value = item.data(Qt.Qt.EditRole)
            setattr(model, field, AppConvert.ObjectConvert(value, types[col]))

    def refreshRowItem(self, row: int):
        item: Qt.QTableWidgetItem = self.item(row, 0)
        if not isinstance(item, Qt.QTableWidgetItem):
            return
        model: DBInterface = item.data(Qt.Qt.UserRole)
        if not isinstance(model, DBInterface):
            return
        self.model().blockSignals(True)
        field: list[str]  = model.__field__
        types: list[type] = model.__types__
        for col, field in enumerate(field):
            item = self.item(row, col)
            if not isinstance(item, Qt.QTableWidgetItem):
                continue
            value = AppConvert.ObjectConvert(getattr(model, field, None), types[col])
            item.setData(Qt.Qt.DisplayRole, value)
            item.setData(Qt.Qt.EditRole, value)
            item.setData(Qt.Qt.ToolTipRole, f'{field}  {types[col]}')
        self.model().blockSignals(False)

    def setItemData(self, item: Qt.QTableWidgetItem, data: DBInterface):
        if not isinstance(item, Qt.QTableWidgetItem):
            return
        item.setData(Qt.Qt.UserRole, data)

    def getItemData(self, item: Qt.QTableWidgetItem) -> DBInterface:
        if isinstance(item, Qt.QTableWidgetItem):
            return item.data(Qt.Qt.UserRole)
        return None

    def setItemField(self, item: Qt.QTableWidgetItem, model: DBInterface, field: str):
        if not isinstance(item, Qt.QTableWidgetItem):
            return
        setattr(item, 'model', model)
        setattr(item, 'field', field)

    def getItemField(self, item: Qt.QTableWidgetItem) -> (DBInterface, str):
        if not isinstance(item, Qt.QTableWidgetItem):
            return None, None
        model = getattr(item, 'model', None)
        field = getattr(item, 'field', None)
        return model, field

    @property
    def isEmpty(self) -> bool:
        return True if not self.hasModels else len(self.Models) == 0

    @property
    def isAction(self) -> bool:
        self.initIsAction()
        return self.IsAction

    @property
    def hasModel    (self) -> bool:
        return self.has_field('Model'    , DBInterface      )

    @property
    def hasMenus    (self) -> bool:
        return self.has_field('Menus'    , ActionMenuBar    )

    @property
    def hasIsAction (self) -> bool:
        return self.has_field('IsAction' , (bool, int)      )

    @property
    def hasModels   (self) -> bool:
        return self.has_field('Models'   , list             )

