"""
EN: Resource manager for the BBW University Research Platform backend.
    - Loads, stores, and provides access to materials, printers, and qualities from CSV files.
    - Acts as a central cache for resource data.
DE: Ressourcenmanager für das Backend der Forschungsplattform der bbw Hochschule.
    - Lädt, speichert und stellt Zugriff auf Materialien, Drucker und Qualitäten aus CSV-Dateien bereit.
    - Dient als zentraler Cache für Ressourcendaten.
"""
from typing import Dict, List, Optional, Any
import logging
from collections import defaultdict
from app.services.daten_manager_csv import DatenManager
from app.models.material import Material
from app.models.qualitaet import Qualitaet
from app.models.drucker import Drucker

class RessourcenManager:
    """
    EN: Manages the lifecycle and access to application resources like materials, printers, and qualities,
        loaded from data sources. It acts as a central cache.
    DE: Verwaltet den Lebenszyklus und den Zugriff auf die aus den Datenquellen
        geladenen Ressourcen wie Materialien, Drucker und Qualitäten. Dient als zentraler Cache.
    """

    def __init__(self):
        """
        EN: Initializes the manager with empty data containers.
        DE: Initialisiert den Manager mit leeren Datencontainern.
        """
        # EN: Dictionaries to store resources, keyed by their name for fast lookups.
        # DE: Wörterbücher zur Speicherung von Ressourcen, indiziert nach ihrem Namen für schnellen Zugriff.
        self.materialien: Dict[str, Material] = {}
        self.qualitaeten: Dict[str, Qualitaet] = {}
        self.drucker: Dict[str, Drucker] = {}

    def lade_alle_ressourcen(self, material_daten_pfad: str, qualitaet_daten_pfad: str, drucker_daten_pfad: str):
        """
        EN: Loads all available resources (materials, qualities, printers) from the specified CSV files.
        DE: Lädt alle verfügbaren Ressourcen (Materialien, Qualitäten, Drucker) aus den angegebenen CSV-Dateien.
        """
        # EN: Load the data from CSVs into lists of objects using the DatenManager.
        # DE: Die Daten aus den CSVs mithilfe des DatenManagers in Listen von Objekten laden.
        materialien_liste = DatenManager.lade_aus_csv(material_daten_pfad, Material)
        qualitaeten_liste = DatenManager.lade_aus_csv(qualitaet_daten_pfad, Qualitaet)
        drucker_liste = DatenManager.lade_aus_csv(drucker_daten_pfad, Drucker)

        # EN: Convert the lists into dictionaries for efficient O(1) access by name.
        # DE: Die Listen in Wörterbücher umwandeln, um einen effizienten O(1)-Zugriff über den Namen zu ermöglichen.
        self.materialien = {m.name: m for m in materialien_liste}
        self.qualitaeten = {q.name: q for q in qualitaeten_liste}
        self.drucker = {d.name: d for d in drucker_liste}

        # EN: Use logging instead of print for better integration into the application's logging system.
        # DE: Logging anstelle von print verwenden für eine bessere Integration in das Logging-System der Anwendung.
        logging.info(f"Ressourcen geladen: "
                     f"{len(self.materialien)} Materialien, "
                     f"{len(self.qualitaeten)} Qualitäten, "
                     f"{len(self.drucker)} Drucker.")

    # --- Getter-Methoden für kontrollierten Zugriff ---
    # EN: Getter methods for controlled access to resources. This is a good practice for encapsulation.
    # DE: Getter-Methoden für den kontrollierten Zugriff auf Ressourcen. Dies ist eine gute Praxis für die Kapselung.

    def get_drucker_by_name(self, name: str) -> Optional[Drucker]:
        """
        EN: Returns a printer object by its name, or None if not found.
        DE: Gibt ein Drucker-Objekt anhand seines Namens zurück, oder None, wenn es nicht gefunden wurde.
        """
        return self.drucker.get(name)

    def get_material_by_name(self, material: str) -> Optional[Material]:
        """
        EN: Returns a material object by its name, or None if not found.
        DE: Gibt ein Material-Objekt anhand seines Namens zurück, oder None, wenn es nicht gefunden wurde.
        """
        return self.materialien.get(material)

    def get_qualitaet_by_name(self, name: str) -> Optional[Qualitaet]:
        """
        EN: Returns a quality object by its name, or None if not found.
        DE: Gibt ein Qualitaet-Objekt anhand seines Namens zurück, oder None, wenn es nicht gefunden wurde.
        """
        return self.qualitaeten.get(name)

    def get_all_materials_for_ui(self) -> Dict[str, List[Dict[str, Any]]]:
        """
        EN: Returns a dictionary of materials grouped by material type (e.g., 'PLA', 'ABS'),
            formatted for the UI.
        DE: Gibt ein Wörterbuch mit Materialien zurück, die nach Materialtyp ('PLA', 'ABS', etc.)
            gruppiert und für die UI formatiert sind.
        """
        grouped_materials = defaultdict(list)

        for m in self.materialien.values():
            material_data = {
                'name': m.name,
                'image_link': m.image_link,
                'cost_kg': m.cost_kg,
                'stock_kg': m.stock_kg
            }
            grouped_materials[m.material].append(material_data)

        return dict(grouped_materials)

    def get_all_drucker_names(self) -> List[str]:
        """
        EN: Returns a list of all loaded printer names, ready for the UI.
        DE: Gibt eine Liste aller geladenen Druckernamen zurück, bereit für die UI.
        """
        return list(self.drucker.keys())

    def get_all_material_names(self) -> List[str]:
        """
        EN: Returns a list of all loaded material names, ready for the UI.
        DE: Gibt eine Liste aller geladenen Materialnamen zurück, bereit für die UI.
        """
        return list(self.materialien.keys())

    def get_all_qualitaet_names(self) -> List[str]:
        """
        EN: Returns a list of all loaded quality names, ready for the UI.
        DE: Gibt eine Liste aller geladenen Qualitätsnamen zurück, bereit für die UI.
        """
        return list(self.qualitaeten.keys())