from datetime import datetime
from typing import Any

from PySide6.QtCore import QAbstractTableModel, QModelIndex
from PySide6.QtGui import Qt, QColor
from kontor_schema.database import ColumnEntry

from .model_config import KontorModelConfig


def get_display_value(value: Any, column_config: dict, window) -> str:
    if isinstance(value, datetime):
        return value.strftime("%Y-%m-%d %M:%M:%S")
    if column_config[ColumnEntry.COLUMN_TYPE] == 'BOOLEAN':
        if value == 1:
            return window.tick
        else:
            return window.cross
    if value is None:
        return ""
    # window.log.info(f"unknown type: {column_config[ColumnEntry.COLUMN_TYPE]} - {type(value)}")
    return str(value)


def get_edit_value(value, column_config, window):
    # window.log.info(f"edit value {value}")
    return str(value)


def get_decoration_value(value: Any, column_config: dict, window):
    if column_config[ColumnEntry.COLUMN_TYPE] == 'BOOLEAN':
        if value == 1:
            return window.tick
        else:
            return window.cross


def get_background_value(value: Any, column_config: dict, window):
    if value is None:
        return QColor('lightgrey')


class KontorTableModel(QAbstractTableModel):

    def __init__(self, model_config: KontorModelConfig):
        super().__init__()
        self._main_window = model_config.main_window
        self._config = model_config
        self._data = []
        self.log = model_config.log

    def __str__(self):
        return f"KontorTableModel({self._config})"

    @property
    def config(self):
        return self._config

    @property
    def raw_data(self):
        return self._data

    def refresh(self):
        # self.log.info("refresh")
        data = self._config.get_data()
        count = 0
        # print(data)
        if data is not None:
            self.beginResetModel()
            self._data.clear()
            self._data = data
            self.endResetModel()
            count = len(data)
            # print(data)
            # print(self._data)
        self.layoutChanged.emit()
        self._main_window.update_status(f"{count} Einträge geladen")

    def rowCount(self, parent=QModelIndex()):
        # self.log.info("rowCount %s: %d", self, len(self._data))
        # The length of the outer list.
        if self._data is None:
            return 0
        return len(self._data)

    def headerData(self, col, orientation, role=Qt.ItemDataRole.DisplayRole):
        # self.log.info(f"{self._config.header[col]}")
        if orientation == Qt.Orientation.Horizontal and role == Qt.ItemDataRole.DisplayRole:
            return self._config.header[col][ColumnEntry.COLUMN_LABEL]
        if orientation == Qt.Orientation.Vertical and role == Qt.ItemDataRole.DisplayRole:
            return str(col + 1)

    def data(self, index, role=Qt.ItemDataRole.DisplayRole):
        if self._data is None:
            return None
        value = self._data[index.row()][index.column()]
        # print('{}:: {}:: {}:: {}: {}'.format(index, role, self._config.header[index.column()][ColumnEntry.COLUMN_TYPE], value, type(value)))
        match role:
            case Qt.ItemDataRole.DisplayRole:
                return get_display_value(value, self._config.header[index.column()], self._config.main_window)
            case Qt.ItemDataRole.EditRole:
                return get_edit_value(value, self._config.header[index.column()], self._config.main_window)
            case Qt.ItemDataRole.DecorationRole:
                return get_decoration_value(value, self._config.header[index.column()], self._config.main_window)
            case Qt.ItemDataRole.BackgroundRole:
                return get_background_value(value, self._config.header[index.column()], self._config.main_window)

    def columnCount(self, index=QModelIndex()):
        # self.log.info("rowCount %s: %d", self, len(self._config.header))
        return len(self._config.header)

    def setData(self, index, value, role=Qt.ItemDataRole.EditRole) -> bool:
        # self._config.log.info(f"{index}: {role}")
        if role == Qt.ItemDataRole.EditRole:
            self._data[index.row()][index.column()] = value
            # self._config.log.info(f"{index.row()}-{index.column()}: {self._data[index.row()][index.column()]}")
            self.dataChanged.emit(index, index)
            return True
        if role == Qt.ItemDataRole.CheckStateRole:
            print("role == Qt.ItemDataRole.CheckStateRole")
            checked = value == Qt.CheckState.Checked
            self._data[index.row()][index.column()] = checked
        return False

    def flags(self, index):
        if self._config.header[index.column()][ColumnEntry.COLUMN_NAME] == 'id':
            return Qt.ItemFlag.ItemIsEnabled
        return Qt.ItemFlag.ItemIsSelectable | Qt.ItemFlag.ItemIsEnabled | Qt.ItemFlag.ItemIsEditable | Qt.ItemFlag.ItemIsUserTristate
