"""
EN: Validation service for the BBW University Research Platform backend.
    - Provides static methods to check business rules and data consistency before calculations.
DE: Validierungsdienst für das Backend der Forschungsplattform der bbw Hochschule.
    - Bietet statische Methoden zur Überprüfung von Geschäftsregeln und Datenkonsistenz vor Berechnungen.
"""

# DE: Stellt eine Sammlung von Validierungsfunktionen als Dienst bereit.
# EN: Provides a collection of validation functions as a service.

# EN: Import model classes for type checking and data access.
# DE: Importieren von Modellklassen für Typüberprüfung und Datenzugriff.
from app.models.drucker import Drucker
from app.models.material import Material
from app.models.teil import Teil
from app.models.qualitaet import Qualitaet

# EN: Import the calculation service to use its methods, and the custom exception for error handling.
# DE: Importieren des Berechnungsdienstes, um dessen Methoden zu verwenden, und der benutzerdefinierten Ausnahme zur Fehlerbehandlung.
from app.ausnahmen.ausnahmeverwaltung import ValidierungsFehler


# EN: A service class containing static methods for business rule and data consistency validation.
# DE: Eine Dienstklasse, die statische Methoden zur Überprüfung von Geschäftsregeln und Datenkonsistenz enthält.
class Validierungsdienst:
    """
    DE: Bietet statische Methoden zur Überprüfung von Geschäftsregeln und Datenkonsistenz vor Berechnungen.
    EN: Provides static methods to check business rules and data consistency before performing calculations.
    """

    @staticmethod
    def pruefe_abmessungen(teil: Teil, drucker: Drucker) -> None:
        """
        DE: Überprüft, ob die Abmessungen des Teils in den Bauraum des Druckers passen. Löst bei einem Fehler eine ValidierungsFehler-Ausnahme aus.
        EN: Checks if the part's dimensions fit within the printer's build volume. Raises a ValidierungsFehler on failure.
        """
        if teil.breite > drucker.max_breite:
            raise ValidierungsFehler(
                f"Teilbreite ({teil.breite} mm) überschreitet die maximale Druckerbreite ({drucker.max_breite} mm).",
                f"Part width ({teil.breite} mm) exceeds the printer's maximum width ({drucker.max_breite} mm)."
            )

        if teil.laenge > drucker.max_laenge:
            raise ValidierungsFehler(
                f"Teillänge ({teil.laenge} mm) überschreitet die maximale Druckerlänge ({drucker.max_laenge} mm).",
                f"Part length ({teil.laenge} mm) exceeds the printer's maximum length ({drucker.max_laenge} mm)."
            )

        if teil.hoehe > drucker.max_hoehe:
            raise ValidierungsFehler(
                f"Teilhöhe ({teil.hoehe} mm) überschreitet die maximale Druckerhöhe ({drucker.max_hoehe} mm).",
                f"Part height ({teil.hoehe} mm) exceeds the printer's maximum height ({drucker.max_hoehe} mm)."
            )

    @staticmethod
    def pruefe_materialbestand(material: Material, benoetigtes_gewicht_kg: float) -> None:
        """
        DE: Überprüft, ob der verfügbare Materialbestand für eine benötigte Menge ausreicht.
        EN: Checks if the available material stock is sufficient for a required amount.
        """
        if material.stock_kg < benoetigtes_gewicht_kg:
            raise ValidierungsFehler(
                f"Nicht genügend Material '{material.name}' verfügbar: benötigt {benoetigtes_gewicht_kg:.2f} kg, vorhanden {material.stock_kg:.2f} kg.",
                f"Not enough material '{material.name}' available: needed {benoetigtes_gewicht_kg:.2f} kg, available {material.stock_kg:.2f} kg."
            )

    @staticmethod
    def pruefe_gueltige_teil_eigenschaften(teil: Teil) -> None:
        """
        DE: Prüft, ob die Eigenschaften des Teils (z.B. Volumen) für Berechnungen gültig sind.
        EN: Checks if the part's properties (e.g., volume) are valid for calculations.
        """
        if teil.volumen is None or teil.volumen <= 0:
            raise ValidierungsFehler(
                "Das Volumen des Teils ist ungültig oder nicht definiert.",
                "The volume of the part is invalid or not defined."
            )

    @staticmethod
    def pruefe_gueltige_material_eigenschaften(material: Material) -> None:
        """
        DE: Prüft, ob die Eigenschaften des Materials (z.B. Dichte, Kosten) für Berechnungen gültig sind.
        EN: Checks if the material's properties (e.g., density, cost) are valid for calculations.
        """
        if material.dichte <= 0:
            raise ValidierungsFehler(
                f"Ungültige Dichte für Material '{material.name}'.",
                f"Invalid density for material '{material.name}'."
            )
        if not hasattr(material, "cost_kg") or material.cost_kg <= 0:
            raise ValidierungsFehler(
                f"Ungültiger Preis pro Kilogramm für Material '{material.name}'.",
                f"Invalid price per kilogram for material '{material.name}'."
            )

    @staticmethod
    def pruefe_gueltige_drucker_eigenschaften(drucker: Drucker) -> None:
        """
        DE: Prüft, ob die Eigenschaften des Druckers (z.B. Faktor, Stundensatz) für Berechnungen gültig sind.
        EN: Checks if the printer's properties (e.g., factor, hourly rate) are valid for calculations.
        """
        if drucker.druckzeit_faktor <= 0:
            raise ValidierungsFehler(
                f"Druckzeit-Faktor des Druckers '{drucker.name}' ist ungültig.",
                f"Print time factor for printer '{drucker.name}' is invalid."
            )
        if not hasattr(drucker, "stundensatz") or drucker.stundensatz <= 0:
            raise ValidierungsFehler(
                f"Stundensatz des Druckers '{drucker.name}' ist ungültig.",
                f"Hourly rate for printer '{drucker.name}' is invalid."
            )

    @staticmethod
    def pruefe_gueltige_qualitaet_eigenschaften(qualitaet: Qualitaet) -> None:
        """
        DE: Prüft, ob die Eigenschaften der Qualität (z.B. Faktor) für Berechnungen gültig sind.
        EN: Checks if the quality's properties (e.g., factor) are valid for calculations.
        """
        if qualitaet.faktor <= 0:
            raise ValidierungsFehler(
                f"Qualitätsfaktor '{qualitaet.faktor}' ist ungültig.",
                f"Quality factor '{qualitaet.faktor}' is invalid."
            )