import uuid
from typing import List, Callable, Any

from PySide6.QtCore import QModelIndex, Qt, QAbstractTableModel, Slot
from PySide6.QtQml import QJSValue
from peewee import Select

from lib.domain.Applicant import Applicant

COLUMNS: list[Callable[[Applicant], Any]] = [
    lambda applicant: applicant.first_name,
    lambda applicant: applicant.last_name,
    lambda applicant: applicant.zip_code.zip_code or None,
    lambda applicant: applicant.zip_code.town.town if applicant.zip_code.id is not None else None
]

COLUMN_NAMES = ["Vorname", "Nachname", "PLZ", "Ort"]


class ApplicantModel(QAbstractTableModel):
    _applicants: Select

    def __init__(self) -> None:
        super().__init__()
        self._applicants = Applicant.select_table_data()

    def rowCount(self, /, parent=...):
        return len(self._applicants)

    def columnCount(self, /, parent=...):
        return len(COLUMNS)

    def data(self, index: QModelIndex, role: int = Qt.ItemDataRole.DisplayRole):
        if role == Qt.ItemDataRole.DisplayRole:
            applicant = self._applicants[index.row()]
            return COLUMNS[index.column()](applicant)
        return None

    @Slot(int, result=dict)
    def applicant(self, row) -> dict:
        applicant = Applicant.get_by_id(self._applicants[row].id)
        return {
            'title': applicant.title,
            "firstName": applicant.first_name,
            "lastName": applicant.last_name,
            "street": applicant.street,
            "houseNumber": applicant.house_number,
            "zipCode": applicant.zip_code_id,
            "phoneNumber": applicant.phone_number,
            "mobileNumber": applicant.mobile_number,
            "emailAddress": applicant.email_address,
            "salutation": applicant.salutation
        }

    @Slot(QJSValue)
    def createApplicant(self, values: QJSValue):
        applicant = Applicant()
        applicant.id = uuid.uuid4()
        applicant.title = values.property("title").toInt()
        applicant.first_name = values.property("firstName").toString()
        applicant.last_name = values.property("lastName").toString()
        applicant.street = values.property("street").toString() or None
        applicant.house_number = values.property("houseNumber").toString() or None
        if values.property("zipCode").toInt() != -1:
            applicant.zip_code = values.property("zipCode").toInt()
        applicant.phone_number = values.property("phoneNumber").toString() or None
        applicant.mobile_number = values.property("mobileNumber").toString() or None
        applicant.email_address = values.property("emailAddress").toString() or None
        applicant.salutation = values.property("salutation").toString() or None
        applicant.save(force_insert=True)
        self._applicants = Applicant.select_table_data()

    def headerData(self, section: int, orientation: Qt.Orientation, role: int = Qt.ItemDataRole.DisplayRole):
        if role == Qt.ItemDataRole.DisplayRole:
            return COLUMN_NAMES[section]
        return None
