using AidA.Data.Entities;
using NHibernate;
using NHibernate.Criterion;
using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Windows;

namespace AidA.Data
{
    public class Database
    {
        public static IList<T> GetAll<T>() where T : class
        {
            return HibernateHelper.GetCurrentSession().CreateCriteria<T>().List<T>();
        }

        public static void InsertAnonymisierungslauf(Anonymisierungslauf anonymisierungslauf, string user)
        {
            ISession session = HibernateHelper.GetCurrentSession();
            ITransaction transaction = session.BeginTransaction();
            anonymisierungslauf.InsTs = DateTime.Now;
            anonymisierungslauf.InsUser = user;
            try
            {
                session.Save(anonymisierungslauf);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }
        }

        public static void UpdateAnonymisierungslauf(Anonymisierungslauf anonymisierungslauf, string user)
        {
            ISession session = HibernateHelper.GetCurrentSession();
            ITransaction transaction = session.BeginTransaction();
            anonymisierungslauf.UpdTs = DateTime.Now;
            anonymisierungslauf.UpdUser = user;
            try
            {
                session.Save(anonymisierungslauf);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }
        }

        public static void SaveAnonymisierungslaufDurchfuehrung(Anonymisierungslauf anonymisierungslauf, IList<Antrag> ZuAnonymisierendeAntraege, string user)
        {
            ISession session = HibernateHelper.GetCurrentSession();
            ITransaction transaction = session.BeginTransaction();

            DateTime ts = DateTime.Now;
            anonymisierungslauf.UpdTs = ts;
            anonymisierungslauf.UpdUser = user;
            bool dbGesichert = false;

            try
            {
                ErstelleDbSicherheitsKopie(anonymisierungslauf.Sicherung);
                dbGesichert = true;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                var text = "Fehler beim Erstellen der Datenbanksicherung:\n\n" +
                    ex.Message + "\n\n" +
                    "Anonymisierungsdaten werden nicht gespeichert!\n" +
                    "Bitte Rechte des Datenbankbenutzers prüfen.";
                MessageBox.Show(text, "Erstellen der Datenbanksicherung fehlgeschlagen", MessageBoxButton.OK, MessageBoxImage.Error);
                anonymisierungslauf.Sicherung = null;
                anonymisierungslauf.AnzahlAnonymisierteAntraege = 0;
            }

            if (dbGesichert)
            {
                try
                {
                    foreach (var anonymisierung in anonymisierungslauf.Anonymisierungen)
                    {
                        session.Save(anonymisierung);
                        anonymisierung.InsTs = ts;
                        anonymisierung.InsUser = user;
                    }
                    foreach (var antrag in ZuAnonymisierendeAntraege)
                    {
                        foreach (var kommunikation in antrag.Kommunikationen)
                        {
                            session.Delete(kommunikation);
                        }
                        session.Save(antrag);
                    }
                    session.SaveOrUpdate(anonymisierungslauf);
                    transaction.Commit();
                }
                catch (Exception ex)
                {
                    transaction.Rollback();
                    var text = "Fehler beim Speichern der Anonymisierungsdaten:\n\n" + ex.Message;
                    MessageBox.Show(text, "Speichern der Anonymisierungsdaten fehlgeschlagen", MessageBoxButton.OK, MessageBoxImage.Error);
                    anonymisierungslauf.AnzahlAnonymisierteAntraege = 0;
                }
            }
        }

        public static void InsertAnonymisierung(Anonymisierung anonymisierung, String user)
        {
            ISession session = HibernateHelper.GetCurrentSession();
            ITransaction transaction = session.BeginTransaction();
            anonymisierung.InsTs = DateTime.Now;
            anonymisierung.InsUser = user;
            try
            {
                session.Save(anonymisierung);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }
        }

        public static void InsertAnonymisierungsausnahme(Anonymisierungsausnahme anonymisierungsausnahme, String user)
        {
            ISession session = HibernateHelper.GetCurrentSession();
            ITransaction transaction = session.BeginTransaction();
            anonymisierungsausnahme.InsTs = DateTime.Now;
            anonymisierungsausnahme.InsUser = user;
            try
            {
                session.Save(anonymisierungsausnahme);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }
        }

        public static void DeleteAnonymisierungsausnahme(Anonymisierungsausnahme anonymisierungsausnahme)
        {
            ISession session = HibernateHelper.GetCurrentSession();
            ITransaction transaction = session.BeginTransaction();
            try
            {
                session.Delete(anonymisierungsausnahme);
                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }
        }

        public static long GetAntragsIdForAntragsNummer(long antragsNummer)
        {
            var c = HibernateHelper.GetCurrentSession().CreateCriteria<Antrag>().Add(Restrictions.Eq("AntragsNummer", antragsNummer));
            Antrag antrag = (Antrag)c.UniqueResult();
            if (antrag != null)
                return antrag.Id;
            return -1;
        }

        public static AntragsStatus GetAntragsStatus(long antragsStatusId)
        {
            var c = HibernateHelper.GetCurrentSession().CreateCriteria<AntragsStatus>().Add(Restrictions.Eq("Id", antragsStatusId));

            return (AntragsStatus) c.UniqueResult();
        }

        public static Anonymisierung GetAnonymisierungForAntrag(long antragsId)
        {
            var c = HibernateHelper.GetCurrentSession().CreateCriteria<Anonymisierung>().Add(Restrictions.Eq("AntragsId", antragsId));
        
            return (Anonymisierung) c.UniqueResult();
        }

        public static IList<Antrag> GetAntraegeForAnsprechpartner (Ansprechpartner ansprechpartner)
        {
            var c = HibernateHelper.GetCurrentSession().CreateCriteria<Antrag>().Add(Restrictions.Eq("Ansprechpartner", ansprechpartner));

            return (IList<Antrag>) c.UniqueResult();
        }

        public static PersonenIdentitaet GetPersonenIdentitaet(string vorname, string nachname, DateTime? geburtsdatum)
        {
            var criteria = HibernateHelper.GetCurrentSession().CreateCriteria<PersonenIdentitaet>()
                .Add(Restrictions.Eq("Vorname", vorname))
                .Add(Restrictions.Eq("Nachname", nachname))
                .Add(Restrictions.Eq("Geburtsdatum", geburtsdatum));

            return (PersonenIdentitaet) criteria.UniqueResult();
        }

        public static IList<PersonenIdentitaet> GetPersonenIdentitaeten(string vorname, string nachname)
        {
            var criteria = HibernateHelper.GetCurrentSession().CreateCriteria<PersonenIdentitaet>()
                .Add(Restrictions.Eq("Vorname", vorname))
                .Add(Restrictions.Eq("Nachname", nachname));

            return criteria.List<PersonenIdentitaet>();
        }

        public static void ErstelleDbSicherheitsKopie(string dateiName)
        {
            const string query = @"BACKUP DATABASE @db TO DISK = @file;";
            String dbBackupVerzeichnis = Properties.Settings.Default.DbBackupVerzeichnis;

            SqlConnection sqlConnection = new SqlConnection(HibernateHelper.GetConnectString());

            SqlCommand sqlCommand = new SqlCommand(query, sqlConnection);
            sqlCommand.Parameters.AddWithValue("@db", "aida-dev");
            sqlCommand.Parameters.AddWithValue("@file", dbBackupVerzeichnis + dateiName);

            sqlConnection.Open();
            int result = sqlCommand.ExecuteNonQuery();
            sqlConnection.Close();
        }

        public static void DbSichern(String dateiname)
        {
            String dbBackupVerzeichnis = Properties.Settings.Default.DbBackupVerzeichnis;

            ISession session = HibernateHelper.GetCurrentSession();

            const string query = @"BACKUP DATABASE @db TO DISK = @file;";

            SqlConnection sqlConnection = new SqlConnection(HibernateHelper.GetConnectString());

            SqlCommand sqlCommand = new SqlCommand(query, sqlConnection);
            sqlCommand.Parameters.AddWithValue("@db", "aida-dev");
            sqlCommand.Parameters.AddWithValue("@file", dateiname);

            sqlConnection.Open();
            try
            {
                int result = sqlCommand.ExecuteNonQuery();
                sqlConnection.Close();
                MessageBox.Show("Datenbank gesichert nach \n\n" + dateiname, "Datenbank gesichert", MessageBoxButton.OK);
            }
            catch (Exception ex)
            {
                var text = "Fehler beim Erstellen der Datenbanksicherung:\n\n" + ex.Message + "\n\n" + ex.StackTrace;
                MessageBox.Show(text, "Erstellen der Datenbanksicherung fehlgeschlagen", MessageBoxButton.OK, MessageBoxImage.Error);
                sqlConnection.Close();
            }
        }

        public static long? InsertPersonenIdentitaet(PersonenIdentitaet personenIdentitaet)
        {
            long? id = null;

            ISession session = HibernateHelper.GetCurrentSession();
            ITransaction transaction = session.BeginTransaction();

            try
            {
                session.Save(personenIdentitaet);
                transaction.Commit();
                id = personenIdentitaet.Id;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                throw ex;
            }

            return id;
        }
    }
}
