from datetime import datetime

from median.models import ItemValide, ListeValide, ListeModel, ListeItemModel, Product, Patient, Service
from common.util import get_counter


class DataMapper:
    """Utility class for mapping data between models"""

    @staticmethod
    def copy_item_to_valide(item: ListeItemModel) -> ItemValide:
        """Copy a ListeItemModel to ItemValide"""
        # Get all fields from item
        item: ListeItemModel = ListeItemModel.get(ListeItemModel.pk == item.pk)

        new_item_valide: ItemValide = ItemValide()

        # Get related model for liste_pk
        liste_valide: ListeValide = ListeValide.get_or_none(ListeValide.liste == item.liste + "-C")
        if not liste_valide:
            liste: ListeModel = ListeModel.get(ListeModel.liste == item.liste)
            liste_valide: ListeValide = DataMapper.copy_list_to_liste_valide(liste)

            if not liste_valide.id_chargement:
                id_chargement = get_counter("EXT_CHARGEMENT_SHV")
                liste_valide.id_chargement = id_chargement
                liste_valide.save()

        if liste_valide:
            new_item_valide.liste_pk = liste_valide.pk
            new_item_valide.item = item.item
            new_item_valide.reference = item.reference
            new_item_valide.quantite_dem = item.qte_dem
            new_item_valide.quantite_serv = item.qte_serv
            new_item_valide.lot = item.lot
            new_item_valide.tperemp = item.tperemp
            new_item_valide.dtprise = item.dtprise
            new_item_valide.moment = item.moment
            new_item_valide.id_pilulier = item.id_pilulier
            new_item_valide.pos_pilulier = item.pos_pilulier
            new_item_valide.tiroir = item.tiroir
            new_item_valide.alveole = item.alveole
            new_item_valide.alveole_theo = item.alveole_theo
            new_item_valide.no_pilulier = item.no_pilulier
            new_item_valide.id_plateau = item.id_plateau
            new_item_valide.pilulier_theo = item.pilulier_theo
            new_item_valide.readonly = item.readonly
            new_item_valide.pk_item = item.pk_item
            new_item_valide.item_wms = item.item_wms
            new_item_valide.heure = item.heure
            new_item_valide.qte_prescrite = item.qte_prescrite
            new_item_valide.fraction = item.fraction
            new_item_valide.type_servi = item.type_servi
            new_item_valide.sous_secteur = item.sous_secteur
            new_item_valide.doublon = 0
            new_item_valide.id_presc = item.id_presc
            new_item_valide.num_ipp = item.num_ipp
            new_item_valide.sejour = item.num_sej
            new_item_valide.pk_doublon = 0
            new_item_valide.serial_doublon = ""
            new_item_valide.info = item.info
            new_item_valide.dtprise = item.dtprise

            # Add Product info
            new_item_valide.designation = Product.get(Product.reference == item.reference).designation

            # Try to get patient information from Patient model or ListeModel
            patient = Patient.get_or_none(Patient.ipp == liste_valide.num_ipp)
            if patient:
                new_item_valide.nom = patient.nom
                new_item_valide.nom_jf = patient.nom_jeune_fille
                new_item_valide.prenom = patient.prenom
                new_item_valide.date_naissance = patient.date_naissance
                new_item_valide.sexe = patient.sexe
            else:
                # Default to empty values if patient not found
                new_item_valide.nom = ""
                new_item_valide.nom_jf = ""
                new_item_valide.prenom = ""
                new_item_valide.date_naissance = None
                new_item_valide.sexe = ""

            # Other patient-related fields from liste
            new_item_valide.chambre = ""  # No direct mapping, need to fetch from somewhere
            new_item_valide.lit = ""  # No direct mapping, need to fetch from somewhere

            # Transfer complete !
            new_item_valide.save()
            item.delete_instance()

            # Remove the list if there are no items left
            if ListeItemModel.select().where(ListeItemModel.liste == item.liste).count() == 0:
                ListeModel.delete().where(ListeModel.liste == item.liste).execute()

        return new_item_valide

    @staticmethod
    def copy_list_to_liste_valide(liste: ListeModel) -> ListeValide:
        """Copy a ListeModel to ListeValide"""
        new_liste_valide: ListeValide = ListeValide()

        # Map fields from ListeModel to ListeValide
        new_liste_valide.chrono = datetime.now()  # Default to current time
        new_liste_valide.liste = liste.liste + "-C"
        if hasattr(liste, "ddeb") and liste.ddeb:
            new_liste_valide.ddeb = liste.ddeb
        new_liste_valide.service = liste.service

        # Try to get service label from Service model
        try:
            service = Service.get_or_none(Service.code == liste.service)
            new_liste_valide.service_label = service.libelle if service else ""
        except Exception:
            new_liste_valide.service_label = ""

        new_liste_valide.num_ipp = liste.num_ipp
        new_liste_valide.num_sej = liste.num_sej
        new_liste_valide.id_prescription = liste.id_prescription if hasattr(liste, "id_prescription") else 0

        # Try to get patient information
        patient = Patient.get_or_none(Patient.ipp == liste.num_ipp)
        if patient:
            new_liste_valide.nom = patient.nom
            new_liste_valide.nom_jf = patient.nom_jeune_fille
            new_liste_valide.prenom = patient.prenom
            new_liste_valide.date_naissance = patient.date_naissance
        else:
            new_liste_valide.nom = ""
            new_liste_valide.nom_jf = ""
            new_liste_valide.prenom = ""
            new_liste_valide.date_naissance = None

        new_liste_valide.type_servi = liste.type_servi
        new_liste_valide.sous_secteur = liste.sous_secteur
        new_liste_valide.id_chariot = liste.id_chariot if hasattr(liste, "id_chariot") else 0
        new_liste_valide.id_pilulier = liste.id_pilulier
        new_liste_valide.id_plateau = liste.id_plateau
        new_liste_valide.id_chargement = liste.id_chargement
        new_liste_valide.adr_pilulier = liste.adr_pilulier
        new_liste_valide.pos_pilulier = liste.pos_pilulier
        new_liste_valide.pk_pilulier = liste.pk_pilulier
        new_liste_valide.imprimer = 0  # Default value
        new_liste_valide.cr_imprimer = 0  # Default value
        new_liste_valide.mode_sache = 0  # Default value
        new_liste_valide.chambre = ""  # No direct mapping in ListeModel
        new_liste_valide.lit = ""  # No direct mapping in ListeModel
        new_liste_valide.adr_carnet = liste.adr_carnet

        new_liste_valide.save()

        # Delete the list if it is empty
        if ListeItemModel.select().where(ListeItemModel.liste == liste.liste).count() == 0:
            liste.delete_instance()

        return new_liste_valide
