using System.Runtime.InteropServices;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Data.Sqlite;
using Microsoft.EntityFrameworkCore;
using System.IO;
using System.Diagnostics;

namespace Watcher.Controllers
{
    [Authorize]
    public class DatabaseController : Controller
    {
        // Backup Infos
        private readonly string _dbPath = Path.Combine(Directory.GetCurrentDirectory(), "persistence", "watcher.db");
        private readonly string _backupFolder = Path.Combine(Directory.GetCurrentDirectory(), "wwwroot", "downloads", "sqlite");

        // Services
        private readonly ILogger<DatabaseController> _logger;

        public class DumpFileInfo
        {
            public string? FileName { get; set; }
            public long SizeKb { get; set; }
            public DateTime Created { get; set; }
        }


        public DatabaseController(IWebHostEnvironment env, ILogger<DatabaseController> logger)
        {
            _logger = logger;

            _backupFolder = Path.Combine(env.WebRootPath, "downloads", "sqlite");

            if (!Directory.Exists(_backupFolder))
            {
                _logger.LogInformation("Backup-Directory neu erstellt");
                Directory.CreateDirectory(_backupFolder);
            }
            else
            {
                _logger.LogInformation("Backup-Directory existiert bereits");
            }
                
        }

        [HttpPost("/maintenance/sqlite-dump")]
        public IActionResult CreateSqlDump()
        {
            try
            {
                // Zielordner sicherstellen
                if (!Directory.Exists(_backupFolder))
                    Directory.CreateDirectory(_backupFolder);

                // Ziel-Dateiname z. B. mit Zeitstempel
                var timestamp = DateTime.Now.ToString("yyyyMMdd_HHmmss");
                var dumpFileName = $"watcher_dump_{timestamp}.sql";
                var dumpFilePath = Path.Combine(_backupFolder, dumpFileName);

                using var connection = new SqliteConnection($"Data Source={_dbPath}");
                connection.Open();

                using var command = connection.CreateCommand();
                command.CommandText = "SELECT sql FROM sqlite_master WHERE type='table' AND sql IS NOT NULL;";
                using var writer = new StreamWriter(dumpFilePath);

                // Write schema
                using (var schemaCmd = connection.CreateCommand())
                {
                    schemaCmd.CommandText = "SELECT sql FROM sqlite_master WHERE type='table'";
                    using var reader = schemaCmd.ExecuteReader();
                    while (reader.Read())
                    {
                        writer.WriteLine(reader.GetString(0) + ";");
                    }
                }

                // Write content
                using (var tableCmd = connection.CreateCommand())
                {
                    tableCmd.CommandText = "SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%'";
                    using var tableReader = tableCmd.ExecuteReader();
                    while (tableReader.Read())
                    {
                        var tableName = tableReader.GetString(0);
                        using var dataCmd = connection.CreateCommand();
                        dataCmd.CommandText = $"SELECT * FROM {tableName}";
                        using var dataReader = dataCmd.ExecuteReader();

                        while (dataReader.Read())
                        {
                            var columns = new string[dataReader.FieldCount];
                            var values = new string[dataReader.FieldCount];

                            for (int i = 0; i < dataReader.FieldCount; i++)
                            {
                                columns[i] = dataReader.GetName(i);
                                var val = dataReader.GetValue(i);
                                values[i] = val == null || val == DBNull.Value
                                    ? "NULL"
                                    : $"'{val.ToString().Replace("'", "''")}'";
                            }

                            writer.WriteLine($"INSERT INTO {tableName} ({string.Join(",", columns)}) VALUES ({string.Join(",", values)});");
                        }
                    }
                }

                writer.Flush();

                //return Ok($"Dump erfolgreich erstellt: {dumpFileName}");

                TempData["DumpMessage"] = "SQLite-Dump erfolgreich erstellt.";
                _logger.LogInformation("SQLite-Dump erfolgreich erstellt.");
                return RedirectToAction("Settings", "System");
            }
            catch (Exception ex)
            {
                //return StatusCode(500, $"Fehler beim Erstellen des Dumps: {ex.Message}");
                TempData["DumpError"] = $"Fehler beim Erstellen des Dumps: {ex.Message}";
                _logger.LogError("Fehler beim Erstellen des Dumps: {message}", ex.Message);
                return RedirectToAction("UserSettings", "User");
            }
        }

        public IActionResult ManageSqlDumps()
        {
            var files = Directory.GetFiles(_backupFolder, "*.sql")
            .Select(f => new DumpFileInfo
            {
                FileName = Path.GetFileName(f),
                SizeKb = new FileInfo(f).Length / 1024,
                Created = System.IO.File.GetCreationTime(f)
            })
            .OrderByDescending(f => f.Created)
            .ToList();

            return View(files);
        }

        [HttpPost]
        public IActionResult Delete(string fileName)
        {
            var filePath = Path.Combine(_backupFolder, fileName);
            if (System.IO.File.Exists(filePath))
            {
                System.IO.File.Delete(filePath);
                TempData["Success"] = $"Backup {fileName} wurde gelöscht.";
            }

            return RedirectToAction("ManageSqlDumps");
        }

        // 🔹 4. Dump wiederherstellen
        [HttpPost]
        public IActionResult Restore(string fileName)
        {
            var filePath = Path.Combine(_backupFolder, fileName);
            if (!System.IO.File.Exists(filePath))
            {
                TempData["Error"] = "Dump nicht gefunden.";
                return RedirectToAction("ManageSqlDumps");
            }

            try
            {
                var dbPath = Path.Combine(Directory.GetCurrentDirectory(), "persistence", "watcher.db"); // anpassen

                // Leere Datenbank
                System.IO.File.WriteAllText(dbPath, "");

                var psi = new ProcessStartInfo
                {
                    FileName = "sqlite3",
                    Arguments = $"\"{dbPath}\" \".read \\\"{filePath}\\\"\"",
                    RedirectStandardOutput = true,
                    RedirectStandardError = true,
                    UseShellExecute = false,
                    CreateNoWindow = true,
                };

                using var proc = Process.Start(psi);
                proc.WaitForExit();

                TempData["Success"] = $"Backup {fileName} wurde wiederhergestellt.";
            }
            catch (Exception ex)
            {
                TempData["Error"] = $"Fehler beim Wiederherstellen: {ex.Message}";
            }

            return RedirectToAction("ManageSqlDumps");
        }
    }

}