import csv
from datetime import datetime
import numpy as np
import os
import webbrowser

class Export:
    """Hilfsfunktionen zum Exportieren von Ergebnissen und Protokollen.

    Die Klasse stellt Methoden zur Verfügung für:

    - Export von Matrizen in CSV-Dateien,
    - Export von Ausgleichungsergebnissen (Skalare und Matrizen) in CSV-Dateien,
    - Erzeugung und Speicherung eines HTML-Protokolls inklusive automatischem Öffnen im Browser.
    """

    @staticmethod
    def matrix_to_csv(dateiname: str, liste_spaltenbeschriftung: list, liste_zeilenbeschriftung: list, Matrix: np.matrix | sp.Matrix,
                      beschriftung_kopfzeile: object = "") -> None:
        """Schreibt eine Matrix mit Zeilen- und Spaltenbeschriftungen in eine CSV-Datei.

        Die Ausgabe erfolgt mit Semikolon als Trennzeichen. Die Kopfzeile enthält optional eine
        zusätzliche Beschriftung sowie Spaltenbeschriftungen.
        Zudem werden Zeilenbeschriftungen durchgeführt.

        :param dateiname: Pfad zu schreibenden CSV-Datei.
        :type dateiname: str
        :param liste_spaltenbeschriftung: Liste der Spaltenbeschriftungen.
        :type liste_spaltenbeschriftung: list
        :param liste_zeilenbeschriftung: Liste der Zeilenbeschriftungen.
        :type liste_zeilenbeschriftung: list
        :param Matrix: Zu exportierende Matrix.
        :type Matrix: np.matrix | sp.Matrix
        :param beschriftung_kopfzeile: Optionaler Eintrag in der linken oberen Zelle der Kopfzeile.
        :type beschriftung_kopfzeile: object
        :return: None
        :rtype: None
        """
        with open(dateiname, "w", newline="", encoding="utf-8") as csvfile:
            writer = csv.writer(csvfile, delimiter=";")

            kopfzeile = [beschriftung_kopfzeile]
            for spaltenbeschriftung in liste_spaltenbeschriftung:
                kopfzeile.append(str(spaltenbeschriftung))
            writer.writerow(kopfzeile)

            for zeilenbeschriftung, zeile in zip(liste_zeilenbeschriftung, Matrix.tolist()):
                zeile_als_text = [zeilenbeschriftung]
                for eintrag in zeile:
                    try:
                        # Dezimaltrenner von Punkt in Komma ändern, weil Python und Excel andere Konventionen vertreten.
                        eintrag_text = str(eintrag).replace(".", ",")
                        try:
                            eintrag_text = float(eintrag_text)
                        except:
                            eintrag_text = eintrag_text
                    except Exception:
                        eintrag_text = str(eintrag)
                    zeile_als_text.append(eintrag_text)
                writer.writerow(zeile_als_text)

    def speichere_html_protokoll(metadaten: dict, ergebnisse: dict) -> None:
        """Erzeugt ein HTML-Protokoll der Ausgleichungsergebnisse und speichert es als Datei.

        Es wird der Unterordner Protokolle angelegt, falls dieser noch nicht existiert.
        Das Protokoll wird als HTML-Datei gespeichert und anschließend im Browser geöffnet.

        Erwartete Schlüssel in metadaten sind u. a. "projekt", "bearbeiter" und "datum".
        Erwartete Schlüssel in ergebnisse sind u. a. "df_globaltest", "df_redundanz",
        "df_ellipsen", "df_konfidenzellipsen", "df_koordinaten_geozentrisch_kartesisch"
        und "df_koordinaten_utm". Die zugehörigen Werte müssen die Methode to_html bereitstellen.

        :param metadaten: Dictionary mit Metadaten zum Protokoll.
        :type metadaten: dict
        :param ergebnisse: Dictionary mit Ergebnisobjekten (z. B. DataFrames) zur HTML-Ausgabe.
        :type ergebnisse: dict
        :return: None
        :rtype: None
        """
        # Pfad für den Ordner erstellen
        ordner = "Protokolle"
        if not os.path.exists(ordner):
            os.makedirs(ordner)

        dateiname = f"{ordner}/Protokoll_{metadaten['projekt']}.html"
        abs_path = os.path.abspath(dateiname)

        # HTML Inhalt zusammenbauen
        html_content = f"""
        <!DOCTYPE html>
        <html lang="de">
        <head>
            <meta charset="UTF-8">
            <style>
                body {{ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif; margin: 40px; line-height: 1.6; color: #333; }}
                h1 {{ color: #2c3e50; border-bottom: 2px solid #2c3e50; }}
                h3 {{ color: #2980b9; margin-top: 30px; }}
                .metadata {{ background: #f9f9f9; padding: 15px; border-radius: 5px; border-left: 5px solid #2980b9; }}
                table {{ border-collapse: collapse; width: 100%; margin-top: 10px; }}
                th, td {{ text-align: left; padding: 8px; border-bottom: 1px solid #ddd; }}
                tr:nth-child(even) {{ background-color: #f2f2f2; }}
                th {{ background-color: #2980b9; color: white; }}
                .footer {{ margin-top: 50px; font-size: 0.8em; color: #7f8c8d; text-align: center; }}
            </style>
            <title>Netzprotokoll - {metadaten['projekt']}</title>
        </head>
        <body>
            <h1>Netzprotokoll: {metadaten['projekt']}</h1>

            <div class="metadata">
                <p><strong>Bearbeiter:</strong> {metadaten['bearbeiter']}</p>
                <p><strong>Datum:</strong> {metadaten['datum']}</p>
                <p><strong>Ausgleichungsmodus:</strong> Methode der kleinsten Quadrate (L2-Norm)</p>
            </div>

            <h3>1. Globaltest</h3>
            {ergebnisse['df_globaltest'].to_html(index=False)}

            <h3>2. Redundanzanteile</h3>
            {ergebnisse['df_redundanz'].to_html(index=False)}

            <h3>3. Standardellipsen</h3>
            {ergebnisse['df_ellipsen'].to_html(index=False)}

            <h3>3. Konfidenzellipsen</h3>
            {ergebnisse['df_konfidenzellipsen'].to_html(index=False)}
            
            <h3>3. Koordinaten Geozentrisch Kartesisch</h3>
            {ergebnisse['df_koordinaten_geozentrisch_kartesisch'].to_html(index=True)}
            
            <h3>3. Koordinaten UTM</h3>
            {ergebnisse['df_koordinaten_utm'].to_html(index=True)}

            <div class="footer">
                Erstellt automatisch am {datetime.now().strftime('%d.%m.%Y um %H:%M:%S')}
            </div>
        </body>
        </html>
        """

        # Datei schreiben
        with open(dateiname, "w", encoding="utf-8") as f:
            f.write(html_content)

        print(f"✅ Protokoll wurde gespeichert unter: {abs_path}")

        # Datei automatisch im Standard-Browser öffnen
        webbrowser.open(f"file://{abs_path}")