using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Documents;
using System.Windows.Shapes;
using System.Xml.Linq;
using Microsoft.Data.Sqlite;
using SQLitePCL;
using static System.Runtime.InteropServices.JavaScript.JSType;


namespace Aborea_Projekt
{
    internal class Datenbank
    {
        public const string DatabaseName = "AboreaDatenbank.sqlite";
        public Datenbank()
        {
            //Schauen, ob die Datenbank existiert
            if (File.Exists(DatabaseName))
                return;


            //Wenn die DB nicht existiert, Daten anlegen
            //1. Rüstungsart durch Konstruktor
            List<Rüstungsart> rüstungsartList = new();                

            rüstungsartList.Add(new Rüstungsart("Ungerüstet",0,0,0,0,0));
            rüstungsartList.Add(new Rüstungsart("Lederrüstung",3,+1,0,9,10));
            rüstungsartList.Add(new Rüstungsart("Kettenhemd",4,+2,-1,130,15));
            rüstungsartList.Add(new Rüstungsart("Halbe Platte",5,+3,-2,200,18));
            rüstungsartList.Add(new Rüstungsart("Plattenpanzer",6,+4,-3,400,30));
            rüstungsartList.Add(new Rüstungsart("Ritterrüstung",7,+5,-4,800,40));
            rüstungsartList.Add(new Rüstungsart("Schild",3,+1,0,11,5));
            rüstungsartList.Add(new Rüstungsart("Turmschild",4,+2,-1,18,10));

            InsertRüstungarten(rüstungsartList);



            //1. Gegenstände durch Konstruktor
            List<Gegenstände> GegenständeList = new();

            GegenständeList.Add(new Gegenstände("Bier",0.5,0.01,"häufig","Halber Liter Bier"));
            GegenständeList.Add(new Gegenstände("Bolzen",1.5,1.6,"mittel","10 Bolzen für Armbrüste"));
            GegenständeList.Add(new Gegenstände("Cidre", 1, 0.01, "häufig", "1L Apfel-Cidre"));
            GegenständeList.Add(new Gegenstände("Fakel", 0.1, 0.01, "häufig", "Brennt 6 Stunden und erhellt 6 m Umkreis"));
            GegenständeList.Add(new Gegenstände("Federkiel und Tinte", 0.1, 0.7, "häufig", "Zum Schreiben mit Tinte"));
            GegenständeList.Add(new Gegenstände("Feuerstein und Zunder", 0.3, 0.22, "mittel", "Zum Entzünden eines Feuers innerhalb von ca. 3 Minuten"));
            GegenständeList.Add(new Gegenstände("Gasthauszimmer", 0 , 0.1, "mittel","Preis für ein Einzelzimmer pro Nacht und Person inklusive Frühstück"));
            GegenständeList.Add(new Gegenstände("Große Heilertasche", 4, 240, "sehr selten", "Bis zu 20 Anwendungen, erlaubt einen Manöverbonus von + 4 auf Wissen(Heilkunde)"));
            GegenständeList.Add(new Gegenstände("Haltbare Nahrung", 5, 0.3, "häufig", "Für eine Woche Nahrung"));
            GegenständeList.Add(new Gegenstände("Heilsalbe", 0.05, 100, "selten", "Verdoppelt die Genesungsrate(5 Anwendungen"));
            GegenständeList.Add(new Gegenstände("Heiltrank", 0.1, 400, "sehr selten", "Regeneriert umgehend 20 Trefferpunkte"));
            GegenständeList.Add(new Gegenstände("Kerze", 0.05, 0.08, "mittel", "Brennt 2 Stunden und erhellt 3 m Umkreis"));
            GegenständeList.Add(new Gegenstände("Kleine Heilertasche", 2, 100, "selten", "Bis zu 20 Anwendungen, erlaubt einen Manöverbonus von +2 auf Wissen (Heilkunde)"));
            GegenständeList.Add(new Gegenstände("Kleiner Hammer", 2, 2.6, "mittel", "Für kleinere Arbeiten oder zum Einschlagen von Kletterhaken"));
            GegenständeList.Add(new Gegenstände("Kletterhaken", 0.1, 6, "selten", "Unterstützt beim Klettern (Bonus von +4); braucht einen Hammer"));
            GegenständeList.Add(new Gegenstände("Köcher", 1.5, 1.2, "häufig", "Platz für bis zu 20 Pfeile"));
            GegenständeList.Add(new Gegenstände("Krähenfüße", 0.1, 1, "selten", "10 Krähenfüße, die Verfolgern Schmerzen bereiten können"));
            GegenständeList.Add(new Gegenstände("Kreide", 0, 0.05, "mittel", "Ein Stück Kreide"));
            GegenständeList.Add(new Gegenstände("Laterne", 1, 2.8, "mittel", "Brennt pro halbem Liter Öl 6 Stunden und erhellt 15 m Umkreis"));
            GegenständeList.Add(new Gegenstände("Mahlzeit", 0, 0.02, "häufig", "Eine übliche Mahlzeit"));
            GegenständeList.Add(new Gegenstände("Metallkugeln (Schleuder)", 1, 0.05, "häufig", "Beutel mit 30 Stück"));
            GegenständeList.Add(new Gegenstände("Öl", 0.5, 0.8, "mittel", "Leicht entzündlich; nötig für Laternen und brennt 6 Stunden in einer Laterne"));
            GegenständeList.Add(new Gegenstände("Pergament", 0.1, 0.6, "mittel", "Ein Blatt Pergament"));
            GegenständeList.Add(new Gegenstände("Pfeile", 1.2, 1, "häufig", "20 Pfeile für Bögen"));
            GegenständeList.Add(new Gegenstände("Pony", 0, 40, "mittel", "7 km/h, trägt bis zu 90 kg"));
            GegenständeList.Add(new Gegenstände("Reitpferd", 0, 90, "mittel", "12 km/h, trägt bis zu 150 kg"));
            GegenständeList.Add(new Gegenstände("Rucksack", 1, 0.44, "mittel", "Kann bis zu 20 kg oder 40 l verstauen"));
            GegenständeList.Add(new Gegenstände("Sattel", 6, 12, "mittel", "Sattel für ein Reittier"));
            GegenständeList.Add(new Gegenstände("Arbeitspferd", 400, 70, "häufig", "Kann 100 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Dietrich", 0.1, 2, "selten", "+1 auf Schlösser öffnen"));
            GegenständeList.Add(new Gegenstände("Elefant", 5500, 1300, "selten", "Kann 500 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Fährfahrt", 0, 0.2, "mittel", "Übersetzen von einer Person"));
            GegenständeList.Add(new Gegenstände("Falle", 1, 1.8, "mittel", "Einfache Tierfalle"));
            GegenständeList.Add(new Gegenstände("Galeere - groß", 0, 200000, "extrem selten", "Bis zu 400 Personen"));
            GegenständeList.Add(new Gegenstände("Galeere - klein", 0, 75000, "sehr selten", "Bis zu 200 Personen"));
            GegenständeList.Add(new Gegenstände("Glasphiole", 0.1, 0.5, "mittel", "100 ml Fassungsvermögen"));
            GegenständeList.Add(new Gegenstände("Glücksbringer", 0.3, 1, "mittel", "Einfacher (nicht-magischer) Talisman"));
            GegenständeList.Add(new Gegenstände("Göttliches Symbol", 0.2, 5, "mittel", "Einfaches Symbol eines Gottes"));
            GegenständeList.Add(new Gegenstände("Handschuhe", 0.2, 3, "mittel", "Lederhandschuhe"));
            GegenständeList.Add(new Gegenstände("Hängematte", 2, 0.3, "mittel", "Stoffhängematte"));
            GegenständeList.Add(new Gegenstände("Hemd", 0.5, 0.5, "häufig", "Einfach"));
            GegenständeList.Add(new Gegenstände("Hose", 1, 0.4, "häufig", "Einfach"));
            GegenständeList.Add(new Gegenstände("Hundeschlitten", 0, 126, "mittel", "Mit 8 Schlittenhunden, kann 200 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Hut", 0.5, 1, "mittel", "Einfach"));
            GegenständeList.Add(new Gegenstände("Kamel", 450, 300, "selten", "Kann 200 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Kanu", 70, 140, "selten", "Kann 350 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Kette", 3, 0.4, "mittel", "Preis und Gewicht pro Meter"));
            GegenständeList.Add(new Gegenstände("Kriegsschiff - groß", 0, 800000, "extrem selten", "Bis zu 1.000 Personen"));
            GegenständeList.Add(new Gegenstände("Kutsche", 1500, 1500, "selten", "Kann 500 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Lama", 100, 160, "selten", "Kann 25 kg transportieren (insbesondere im Gebirge)"));
            GegenständeList.Add(new Gegenstände("Maultier", 200, 50, "häufig", "Kann 150 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Ochse", 1000, 170, "häufig", "Kann 350 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Pferdekarren", 200, 60, "mittel", "Kann 400 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Planwagen", 450, 160, "mittel", "Kann 700 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Ruderboot", 100, 80, "mittel", "Kann 500 kg transportieren"));
            GegenständeList.Add(new Gegenstände("Satteltaschen", 5, 1.8, "häufig", "Kann bis zu 8 kg fassen"));
            GegenständeList.Add(new Gegenstände("Schiffsreise", 0, 1, "mittel", "Koje auf einem Schiff"));
            GegenständeList.Add(new Gegenstände("Schlachtross", 600, 140, "selten", "Kann 200 kg transportieren, gewährt +2 auf berittenen Kampf"));
            GegenständeList.Add(new Gegenstände("Schloss", 0.5, 6, "mittel", "Eisenschloss (MS 8) mit einem Schlüssel"));
            GegenständeList.Add(new Gegenstände("Segelboot (10 m)", 0, 1600, "selten", "Bis zu 8 Personen"));
            GegenständeList.Add(new Gegenstände("Segelschiff - groß", 0, 60000, "sehr selten", "Bis zu 200 Personen"));
            GegenständeList.Add(new Gegenstände("Segelschiff - mittel", 0, 7500, "selten", "Bis zu 40 Personen"));
            GegenständeList.Add(new Gegenstände("Seil mit Wurfhaken", 5, 5, "mittel", "10 m Seil mit Wurfhaken"));
            GegenständeList.Add(new Gegenstände("Spiegel", 0.2, 8, "mittel", "Metallspiegel"));
            GegenständeList.Add(new Gegenstände("Stiefel", 2, 2.4, "häufig", "Einfach"));
            GegenständeList.Add(new Gegenstände("Umhang", 1.5, 1.8, "häufig", "Einfach"));
            GegenständeList.Add(new Gegenstände("Verstärktes Seil", 0.3, 0.3, "mittel", "Hält dreimal mehr Gewicht als normales Seil"));
            GegenständeList.Add(new Gegenstände("Waffengürtel", 0.5, 1, "häufig", "Kann zwei Waffen halten"));
            GegenständeList.Add(new Gegenstände("Schlafrolle", 4, 1.2, "häufig", "Wärmt nachts; hält durchschnittlich 2 Jahre"));
            GegenständeList.Add(new Gegenstände("Seil", 0.2, 0.1, "häufig", "Stabiles Seil. Kann Bonus auf Manöver geben (beispielsweise Athletik zum Klettern)"));
            GegenständeList.Add(new Gegenstände("Stallplatz", 0, 0.01, "-", "Für einen Tag Platz und Pflege für ein Tier"));
            GegenständeList.Add(new Gegenstände("Wasserbeutel", 0.1, 0.02, "häufig", "Für 1 l Flüssigkeit"));
            GegenständeList.Add(new Gegenstände("Wein", 0.3, 0.02, "häufig", "0.3 l Verdünnter Wein"));
            GegenständeList.Add(new Gegenstände("Zelt", 3, 5, "mittel", "Bietet zwei Personen Schutz"));

            InsertGegenstände(GegenständeList);
        }

        private void InsertRüstungarten(List<Rüstungsart> list)
        {
            //Rüstungsart in die DB speichern
            using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
            {
                connection.Open();// Verbindung zur SQLite-Datenbank öffnen

                var command = connection.CreateCommand();
                // SQL-Befehl zur Erstellung der Tabelle "Gegenstände" falls sie nicht existiert
                string create = "CREATE TABLE Rüstungen(Name varchar(255) NOT NULL, minStärke int, RüstungBonus int, Manöver int, KostenTT double,Gewicht double, PRIMARY KEY (Name));";
                string items = "";// String zur Speicherung der INSERT-Statements vorbereiten
                // Schleife über die Liste der Gegenstände, um SQL-Befehl zum Einfügen vorzubereiten
                foreach (var item in list)
                {
                    // Dynamisches Erstellen von SQL-INSERT-Befehl für jedes Gegenstand-Element
                    items += "INSERT INTO Rüstungen (Name, minStärke,RüstungBonus,Manöver,KostenTT,Gewicht) VALUES ('" + item.Name + "', " + item.minStärke + "," + item.RüstungBonus + "," + item.Manöver + "," + item.KostenTT.ToString(System.Globalization.CultureInfo.InvariantCulture) + "," + item.Gewicht.ToString(System.Globalization.CultureInfo.InvariantCulture) + ");";
                }
                // Kombinieren des CREATE-Befehls mit den vorbereiteten INSERT-Befehlen
                command.CommandText = create + items;
                // SQL-Befehl ausführen
                command.ExecuteNonQuery();
                // Verbindung zur SQLite-Datenbank schließen
                connection.Close();
            }

        }

        private void InsertGegenstände(List<Gegenstände> list)
        {
            //Gegenstände in die DB speichern
            using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
            {
                connection.Open();// Verbindung zur SQLite-Datenbank öffnen

                var command = connection.CreateCommand();
                // SQL-Befehl zur Erstellung der Tabelle "Gegenstände" falls sie nicht existiert
                string create = "CREATE TABLE Gegenstände(Name varchar(255) NOT NULL,Gewicht double,KostenTT double, Häufigkeit varchar(255),Funktion varchar(255) ,PRIMARY KEY (Name));";
                string items = ""; // String zur Speicherung der INSERT-Statements vorbereiten
                // Schleife über die Liste der Gegenstände, um SQL-Befehl zum Einfügen vorzubereiten
                foreach (var item in list)
                {
                    // Dynamisches Erstellen von SQL-INSERT-Befehl für jedes Gegenstand-Element
                    items += "INSERT INTO Gegenstände (Name, Gewicht, KostenTT, Häufigkeit,Funktion) VALUES ('" + item.Name + "', " + item.Gewicht.ToString(System.Globalization.CultureInfo.InvariantCulture) + "," + item.KostenTT.ToString(System.Globalization.CultureInfo.InvariantCulture) + ",'" + item.Häufigkeit + "','" + item.Funktion + "');";
                }
                // Kombinieren des CREATE-Befehls mit den vorbereiteten INSERT-Befehlen
                command.CommandText = create + items;
                // SQL-Befehl ausführen
                command.ExecuteNonQuery();
                // Verbindung zur SQLite-Datenbank schließen
                connection.Close();
            }

        }

        internal static LinkedList<Rüstungsart> GetRüstungsarten()
        {
            //Rüstungsart von der DB abrufen
            // Verbindung zur SQLite-Datenbank erstellen, um Rüstungsarten aus der Datenbank abzurufen
            using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
            {
                connection.Open(); // Verbindung öffnen

                // SQL-Befehl zum Abrufen aller Einträge aus der Tabelle "Rüstungen"
                var command = connection.CreateCommand();
                command.CommandText = "SELECT * FROM Rüstungen";// SQL-Query, um alle Einträge aus der Tabelle "Rüstungen" zu lesen
                SqliteDataReader sqlDR = command.ExecuteReader();// Datenleser erstellen, um die Ergebnisse zu lesen

                // Eine LinkedList erstellen, um die abgerufenen Rüstungsarten zu speichern
                LinkedList<Rüstungsart> rüstungsartList = new LinkedList<Rüstungsart>();

                // Schleife zum Durchlaufen der Datensätze aus der Datenbankabfrage
                while (sqlDR.Read())
                {
                    // Für jeden Datensatz ein neues Rüstungsart-Objekt erstellen und zur LinkedList hinzufügen
                    // Achtung: Die Spaltennamen wie "Name", "minStärke", "RüsungsBonus" usw. müssen korrekt existieren
                    rüstungsartList.AddLast(new Rüstungsart(sqlDR.GetString("Name"), sqlDR.GetInt32("minStärke"), sqlDR.GetInt32("RüstungBonus"), sqlDR.GetInt32("Manöver"), sqlDR.GetDouble("KostenTT"), sqlDR.GetDouble("Gewicht")));
                }
                connection.Close();// Verbindung zur Datenbank schließen

                // Die gefüllte Liste von Rüstungsarten zurückgeben
                return rüstungsartList;
            }
        }

        internal static LinkedList<Gegenstände> GetGegenstände()
        {
            //Gegenstände von der DB abrufen
            // Verbindung zur SQLite-Datenbank herstellen
            using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
            {
                connection.Open();// Verbindung öffnen

                // SQL-Befehl erstellen, um alle Einträge aus der Tabelle "Gegenstände" abzurufen
                var command = connection.CreateCommand();
                command.CommandText = "SELECT * FROM Gegenstände";
                // Datenleser initialisieren, um die Ergebnisse der SQL-Abfrage zu verarbeiten
                SqliteDataReader sqlDR = command.ExecuteReader();

                // Eine LinkedList erstellen, um die Gegenstände zu speichern
                LinkedList<Gegenstände> GegenständeList = new LinkedList<Gegenstände>();

                // Schleife über die Ergebnisse der Abfrage
                while (sqlDR.Read())
                {
                    // Gegenstand aus den Daten der Datenbank erstellen und zur Liste hinzufügen
                    // Hinweis: "sqlDR.GetString" und "sqlDR.GetDouble" erfordern korrekte Spaltennamen
                    GegenständeList.AddLast(new Gegenstände(sqlDR.GetString("Name"), sqlDR.GetDouble("Gewicht"), sqlDR.GetDouble("KostenTT"), sqlDR.GetString("Häufigkeit"), sqlDR.GetString("Funktion")));
                    
                }
                // Verbindung schließen
                connection.Close();

                // Rückgabe der Liste von Gegenständen
                return GegenständeList;
            }
        }


        public static void SpeichereRüstungsart(Rüstungsart rüstung)
        {
            using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
            {
                connection.Open();

                // SQL-Befehl zur Erstellung der Tabelle (falls sie noch nicht existiert)
                var createCommand = connection.CreateCommand();
                createCommand.CommandText = @"
                CREATE TABLE IF NOT EXISTS Rüstungen (
                    Name TEXT NOT NULL PRIMARY KEY,
                    minStärke INT,
                    RüstungBonus INT,
                    Manöver INT,
                    KostenTT REAL,
                    Gewicht REAL
                );";
                createCommand.ExecuteNonQuery();

                // SQL-Befehl zum Einfügen der neuen Rüstung
                var insertCommand = connection.CreateCommand();
                insertCommand.CommandText = @"
                INSERT INTO Rüstungen (Name, minStärke, RüstungBonus, Manöver, KostenTT, Gewicht)
                VALUES (@Name, @minStärke, @RüstungBonus, @Manöver, @KostenTT, @Gewicht);";
                insertCommand.Parameters.AddWithValue("@Name", rüstung.Name);
                insertCommand.Parameters.AddWithValue("@minStärke", rüstung.minStärke);
                insertCommand.Parameters.AddWithValue("@RüstungBonus", rüstung.RüstungBonus);
                insertCommand.Parameters.AddWithValue("@Manöver", rüstung.Manöver);
                insertCommand.Parameters.AddWithValue("@KostenTT", rüstung.KostenTT);
                insertCommand.Parameters.AddWithValue("@Gewicht", rüstung.Gewicht);

                insertCommand.ExecuteNonQuery();
            }
        }

        public static void SpeichereGegenstand(Gegenstände neuerGegenstand)
        {
            try
            {
                using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
                {
                    connection.Open();

                    // Tabelle erstellen, falls sie nicht existiert
                    var createCommand = connection.CreateCommand();
                    createCommand.CommandText = @"
                        CREATE TABLE IF NOT EXISTS Gegenstände (
                        Name varchar(255) NOT NULL,
                        Gewicht double,
                        KostenTT double,
                        Häufigkeit varchar(255),
                        Funktion varchar(255),
                        PRIMARY KEY (Name)
                            );";
                    createCommand.ExecuteNonQuery();

                    // Gegenstand einfügen
                    var insertCommand = connection.CreateCommand();
                    insertCommand.CommandText = @"
                        INSERT INTO Gegenstände (Name, Gewicht, KostenTT, Häufigkeit, Funktion)
                        VALUES (@Name, @Gewicht, @KostenTT, @Häufigkeit, @Funktion);";

                    insertCommand.Parameters.AddWithValue("@Name", neuerGegenstand.Name);
                    insertCommand.Parameters.AddWithValue("@Gewicht", neuerGegenstand.Gewicht);
                    insertCommand.Parameters.AddWithValue("@KostenTT", neuerGegenstand.KostenTT);
                    insertCommand.Parameters.AddWithValue("@Häufigkeit", neuerGegenstand.Häufigkeit);
                    insertCommand.Parameters.AddWithValue("@Funktion", neuerGegenstand.Funktion);

                    insertCommand.ExecuteNonQuery();
                    connection.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Fehler beim Speichern des Gegenstands: " + ex.Message, ex);
            }
        }

        internal static void LöscheGegenstand(string gegenstandName)
        {
            try
            {
                using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
                {
                    connection.Open();

                    // Gegenstand löschen
                    var deleteCommand = connection.CreateCommand();
                    deleteCommand.CommandText = @"
                                                DELETE FROM Gegenstände 
                                                WHERE Name = @Name;";

                    deleteCommand.Parameters.AddWithValue("@Name", gegenstandName);  // 'gegenstandName' ist der Name des Gegenstands, den Sie löschen möchten.

                    deleteCommand.ExecuteNonQuery();
                    connection.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Fehler beim Löschen des Gegenstands: " + ex.Message, ex);
            }

        }

        internal static void LöscheRüstung(string rüstungName)
        {
            try
            {
                using (var connection = new SqliteConnection("Data Source=" + DatabaseName))
                {
                    connection.Open();

                    // Gegenstand löschen
                    var deleteCommand = connection.CreateCommand();
                    deleteCommand.CommandText = @"
                                                DELETE FROM Rüstungen 
                                                WHERE Name = @Name;";

                    deleteCommand.Parameters.AddWithValue("@Name", rüstungName);  // 'gegenstandName' ist der Name des Gegenstands, den Sie löschen möchten.

                    deleteCommand.ExecuteNonQuery();
                    connection.Close();
                }
            }
            catch (Exception ex)
            {
                throw new Exception("Fehler beim Löschen des Gegenstands: " + ex.Message, ex);
            }
        }
    }
}
