using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using DirectoryCreator.Models;
using DirectoryCreator.ViewModels;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Windows;

namespace DirectoryCreator
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            DataContext = new MainWindowViewModel();
        }
    }
}

namespace DirectoryCreator.ViewModels
{
    public partial class MainWindowViewModel : ObservableObject
    {
        private readonly string configDirectory = "Configurations";
        private FolderConfig currentConfig;

        [ObservableProperty]
        private string lastProjectNumber;

        [ObservableProperty]
        private string newProjectName;

        [ObservableProperty]
        private string basePath;

        [ObservableProperty]
        private ObservableCollection<FolderConfig> availableConfigurations;

        [ObservableProperty]
        private FolderConfig selectedConfiguration;

        public MainWindowViewModel()
        {
            IsDarkTheme = Properties.Settings.Default.IsDarkTheme;
            ThemeManager.SetTheme(IsDarkTheme);
            AvailableConfigurations = new ObservableCollection<FolderConfig>();
            LoadConfigurations();
        }

        private void LoadConfigurations()
        {
            try
            {
                // Asegurar que existe el directorio de configuraciones
                if (!Directory.Exists(configDirectory))
                {
                    Directory.CreateDirectory(configDirectory);

                    // Si no existe, mover el archivo de configuración por defecto
                    if (File.Exists("folderConfig.json"))
                    {
                        File.Move("folderConfig.json", Path.Combine(configDirectory, "default.json"));
                    }
                }

                // Cargar todas las configuraciones
                var jsonFiles = Directory.GetFiles(configDirectory, "*.json");
                if (jsonFiles.Length == 0)
                {
                    MessageBox.Show("No se encontraron archivos de configuración.", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                var options = new JsonSerializerOptions
                {
                    PropertyNameCaseInsensitive = true,
                    AllowTrailingCommas = true
                };

                AvailableConfigurations.Clear();
                foreach (var jsonFile in jsonFiles)
                {
                    var jsonString = File.ReadAllText(jsonFile);
                    var config = JsonSerializer.Deserialize<FolderConfig>(jsonString, options);
                    if (config != null)
                    {
                        // Si no tiene descripción, usar el nombre del archivo
                        if (string.IsNullOrEmpty(config.Description))
                        {
                            config.Description = Path.GetFileNameWithoutExtension(jsonFile);
                        }
                        AvailableConfigurations.Add(config);
                    }
                }

                // Seleccionar la primera configuración por defecto
                if (AvailableConfigurations.Count > 0)
                {
                    SelectedConfiguration = AvailableConfigurations[0];
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error al cargar las configuraciones: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        [RelayCommand]
        private void OpenBaseFolder()
        {
            try
            {
                if (Directory.Exists(BasePath))
                {
                    Process.Start("explorer.exe", BasePath);
                }
                else
                {
                    MessageBox.Show($"La carpeta base no existe: {BasePath}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error al abrir la carpeta base: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private void LoadLastProjectNumber()
        {
            try
            {
                if (string.IsNullOrEmpty(BasePath) || !Directory.Exists(BasePath))
                {
                    NewProjectName = "001 - ";
                    return;
                }

                var directories = Directory.GetDirectories(BasePath)
                    .Select(d => new DirectoryInfo(d).Name)
                    .ToList();

                var regex = new System.Text.RegularExpressions.Regex(@"^(\d{1,3})\s-\s");
                var projectNumbers = new HashSet<int>();

                foreach (var dirName in directories)
                {
                    var match = regex.Match(dirName);
                    if (match.Success && int.TryParse(match.Groups[1].Value, out int number))
                    {
                        projectNumbers.Add(number);
                    }
                }

                var sortedNumbers = projectNumbers.OrderByDescending(n => n).ToList();
                int lastValidNumber = -1;
                string lastProject = "";

                foreach (int number in sortedNumbers)
                {
                    if (projectNumbers.Contains(number - 1) && projectNumbers.Contains(number - 2))
                    {
                        lastValidNumber = number;
                        lastProject = directories.First(d => regex.Match(d).Success &&
                            int.Parse(regex.Match(d).Groups[1].Value) == number);
                        break;
                    }
                }

                LastProjectNumber = lastProject;
                NewProjectName = lastValidNumber >= 0 ? $"{(lastValidNumber + 1):00} - " : "01 - ";

                if (lastValidNumber < 0)
                {
                    MessageBox.Show("No se encontró una secuencia válida de al menos 3 números consecutivos.\nSe iniciará desde 01.",
                        "Información", MessageBoxButton.OK, MessageBoxImage.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error al cargar el último proyecto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                NewProjectName = "001 - ";
            }
        }

        [RelayCommand]
        private void EditConfigurations()
        {
            var window = new ConfigEditorWindow
            {
                Owner = System.Windows.Application.Current.MainWindow
            };

            if (SelectedConfiguration != null)
            {
                var configPath = Directory.GetFiles(configDirectory, "*.json")
                    .FirstOrDefault(f =>
                    {
                        var config = JsonSerializer.Deserialize<FolderConfig>(
                            File.ReadAllText(f),
                            new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
                        return config?.Description == SelectedConfiguration.Description;
                    });

                window.DataContext = new ConfigEditorViewModel(window, SelectedConfiguration, configPath);
            }
            else
            {
                window.DataContext = new ConfigEditorViewModel(window);
            }

            if (window.ShowDialog() == true)
            {
                LoadConfigurations();
            }
        }

        [ObservableProperty]
        private bool isDarkTheme;

        partial void OnIsDarkThemeChanged(bool value)
        {
            ThemeManager.SetTheme(value);
            // Opcional: Guardar la preferencia del usuario
            Properties.Settings.Default.IsDarkTheme = value;
            Properties.Settings.Default.Save();
        }

        [ObservableProperty]
        private ObservableCollection<string> existingProjects = new();

        [ObservableProperty]
        private string selectedProject;

        private void LoadExistingProjects()
        {
            try
            {
                if (string.IsNullOrEmpty(BasePath) || !Directory.Exists(BasePath))
                {
                    ExistingProjects = new ObservableCollection<string>();
                    return;
                }

                var directories = Directory.GetDirectories(BasePath)
                    .Select(d => new DirectoryInfo(d).Name)
                    .OrderByDescending(name => name)
                    .ToList();

                ExistingProjects = new ObservableCollection<string>(directories);
                
                // Seleccionar el LastProjectNumber si existe
                if (ExistingProjects.Count > 0)
                {
                    if (!string.IsNullOrEmpty(LastProjectNumber) && ExistingProjects.Contains(LastProjectNumber))
                    {
                        SelectedProject = LastProjectNumber;
                    }
                    else
                    {
                        SelectedProject = ExistingProjects[0];
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error al cargar proyectos existentes: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                ExistingProjects = new ObservableCollection<string>();
            }
        }

        partial void OnSelectedConfigurationChanged(FolderConfig value)
        {
            if (value != null)
            {
                currentConfig = value;
                BasePath = value.BasePath;
                LoadLastProjectNumber();
                LoadExistingProjects(); // Cargar proyectos existentes cuando cambia la configuración
            }
        }

        [RelayCommand]
        private async Task RenameProject()
        {
            if (string.IsNullOrEmpty(SelectedProject))
            {
                MessageBox.Show("Por favor seleccione un proyecto para renombrar", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            var result = Microsoft.Windows.Controls.InputDialog.Show(
                "Renombrar Proyecto",
                "Ingrese el nuevo nombre del proyecto:",
                SelectedProject);

            if (result.IsOk)
            {
                string newName = result.Result;
                if (string.IsNullOrWhiteSpace(newName))
                {
                    MessageBox.Show("El nombre no puede estar vacío", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                    return;
                }

                try
                {
                    foreach (var structure in currentConfig.FolderStructures)
                    {
                        var basePath = structure.BasePath.Replace("{year}", DateTime.Now.Year.ToString());
                        var oldPath = Path.Combine(basePath, SelectedProject);
                        var newPath = Path.Combine(basePath, newName);

                        if (Directory.Exists(oldPath))
                        {
                            if (Directory.Exists(newPath))
                            {
                                MessageBox.Show($"Ya existe un directorio con el nombre: {newName}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                                return;
                            }

                            Directory.Move(oldPath, newPath);
                        }
                    }

                    MessageBox.Show("Proyecto renombrado exitosamente!", "Éxito", MessageBoxButton.OK, MessageBoxImage.Information);
                    LoadExistingProjects(); // Recargar la lista de proyectos
                    SelectedProject = newName;
                }
                catch (Exception ex)
                {
                    MessageBox.Show($"Error al renombrar el proyecto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                }
            }
        }

        // Agregar este método en la clase MainWindowViewModel
        [RelayCommand]
        private void DeleteProject()
        {
            if (string.IsNullOrEmpty(SelectedProject))
            {
                MessageBox.Show("Por favor seleccione un proyecto para eliminar", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            try
            {
                // Recopilar todos los directorios a verificar
                List<string> directoriesToCheck = new List<string>();
                List<string> nonEmptyDirectories = new List<string>();

                // Primero encontrar todos los directorios del proyecto
                foreach (var structure in currentConfig.FolderStructures)
                {
                    var basePath = structure.BasePath.Replace("{year}", DateTime.Now.Year.ToString());
                    var projectPath = Path.Combine(basePath, SelectedProject);

                    if (Directory.Exists(projectPath))
                    {
                        directoriesToCheck.Add(projectPath);
                    }
                }

                if (!directoriesToCheck.Any())
                {
                    MessageBox.Show("No se encontraron directorios para eliminar.", "Información", MessageBoxButton.OK, MessageBoxImage.Information);
                    return;
                }

                // Verificar que todos los directorios estén vacíos
                foreach (var directory in directoriesToCheck)
                {
                    if (!IsDirectoryEmpty(directory))
                    {
                        nonEmptyDirectories.Add(directory);
                    }
                }

                // Si hay directorios con contenido, mostrar mensaje y cancelar
                if (nonEmptyDirectories.Any())
                {
                    string message = "Los siguientes directorios contienen archivos y no pueden ser eliminados:\n\n";
                    message += string.Join("\n", nonEmptyDirectories);
                    message += "\n\nDebe vaciar estos directorios antes de poder eliminar el proyecto.";
                    MessageBox.Show(message, "Directorios no vacíos", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }

                // Si todos están vacíos, pedir confirmación
                var result = MessageBox.Show(
                    $"Se eliminarán los siguientes directorios:\n\n{string.Join("\n", directoriesToCheck)}\n\n¿Está seguro que desea continuar?",
                    "Confirmar eliminación",
                    MessageBoxButton.YesNo,
                    MessageBoxImage.Warning);

                if (result == MessageBoxResult.Yes)
                {
                    // Eliminar todos los directorios
                    foreach (var directory in directoriesToCheck)
                    {
                        if (Directory.Exists(directory))
                        {
                            Directory.Delete(directory, false); // false porque ya sabemos que están vacíos
                        }
                    }

                    MessageBox.Show("Proyecto eliminado exitosamente!", "Éxito", MessageBoxButton.OK, MessageBoxImage.Information);
                    LoadExistingProjects(); // Recargar la lista de proyectos
                    SelectedProject = null;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error al eliminar el proyecto: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        private bool IsDirectoryEmpty(string path)
        {
            try
            {
                return !Directory.EnumerateFileSystemEntries(path, "*", SearchOption.AllDirectories).Any();
            }
            catch (Exception)
            {
                return false;
            }
        }

        [RelayCommand]
        private void CreateDirectories()
        {
            if (string.IsNullOrEmpty(NewProjectName))
            {
                MessageBox.Show("Por favor ingrese un nombre de proyecto!", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            if (currentConfig == null)
            {
                MessageBox.Show("Por favor seleccione una configuración!", "Advertencia", MessageBoxButton.OK, MessageBoxImage.Warning);
                return;
            }

            try
            {
                foreach (var structure in currentConfig.FolderStructures)
                {
                    var basePath = structure.BasePath.Replace("{year}", DateTime.Now.Year.ToString());
                    var projectPath = Path.Combine(basePath, NewProjectName);

                    if (Directory.Exists(projectPath))
                    {
                        MessageBox.Show($"El directorio ya existe: {projectPath}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
                        return;
                    }

                    Directory.CreateDirectory(projectPath);

                    foreach (var subfolder in structure.Subfolders)
                    {
                        var subfolderPath = Path.Combine(projectPath, subfolder);
                        Directory.CreateDirectory(subfolderPath);
                    }
                }

                Process.Start("explorer.exe", Path.Combine(BasePath, NewProjectName));
                MessageBox.Show("Directorios creados exitosamente!", "Éxito", MessageBoxButton.OK, MessageBoxImage.Information);
                LoadLastProjectNumber();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error al crear directorios: {ex.Message}", "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }
}