using System.Configuration;
using System.Data;
using System.Windows;
using System;
using System.Windows.Forms;
using Application = System.Windows.Application;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Globalization;
using System.Windows.Data;
using System.Runtime.InteropServices;

namespace GTPCorrgir
{
    public partial class App : Application
    {
        gtpask GTP = new gtpask();
        NotifyIcon notificacion;
        System.Windows.Forms.Timer timer;
        bool CorreccionFinalizada = false;
        Stopwatch stopwatch = new Stopwatch();
        private notificacion notificationWindow;
        private readonly int TimeoutSeconds = 60;
        private CancellationTokenSource _cancellationTokenSource;
        private Window _mainWindow;

        KeyboardHelper pasteLogic = new KeyboardHelper();

        protected override async void OnStartup(StartupEventArgs e)
        {
            ShutdownMode = ShutdownMode.OnExplicitShutdown;
            base.OnStartup(e);
            _cancellationTokenSource = new CancellationTokenSource();

            try
            {
                pasteLogic.SaveCurrentWindow();
                if (Opciones.Instance.modo == Opciones.modoDeUso.Menu)
                {
                    _mainWindow = new ContextMenuWindow();
                    (_mainWindow as ContextMenuWindow).Closed += async (s, args) =>
                    {
                        if (Opciones.Instance.modo != Opciones.modoDeUso.Menu)
                        {
                            await InitializeSelectedMode();
                        }
                        else
                        {
                            Application.Current.Shutdown();
                        }
                    };
                    _mainWindow.Show();
                }
                else
                {
                    await InitializeSelectedMode();
                }
            }
            catch (Exception ex)
            {
                GTP.Log.Log($"Error en OnStartup: {ex.Message}");
                ShowCustomNotification("Error", "Se produjo un error al iniciar la aplicación");
                Application.Current.Shutdown();
            }
        }

        private async Task InitializeSelectedMode()
        {
            switch (Opciones.Instance.modo)
            {
                case Opciones.modoDeUso.OCRaTexto:
                    _mainWindow = new ScreenCaptureWindow();
                    _mainWindow.Closed += (s, e) => Application.Current.Shutdown();
                    break;

                case Opciones.modoDeUso.Chat:
                    _mainWindow = new Chat(GTP);
                    _mainWindow.Closed += (s, e) => Application.Current.Shutdown();
                    break;

                case Opciones.modoDeUso.Corregir:
                case Opciones.modoDeUso.Ortografia:
                case Opciones.modoDeUso.Traducir_a_Espanol:
                case Opciones.modoDeUso.Traducir_a_Ingles:
                case Opciones.modoDeUso.Traducir_a_Italiano:
                case Opciones.modoDeUso.Traducir_a_Portugues:
                    await HandleTextCorrection();
                    return;
            }

            if (_mainWindow != null)
                _mainWindow.Show();
        }

        private async Task HandleTextCorrection()
        {
            if (Opciones.Instance.AutoCopy)
            {
                await pasteLogic.AutoCopyFromActiveWindow();
            }

            if (!System.Windows.Clipboard.ContainsText())
            {
                ShowCustomNotification("Error", "No hay texto para procesar");
                Application.Current.Shutdown();
                return;
            }

            GTP.TextoACorregir = await ClipboardHelper.GetText();
            stopwatch.Start();
            ShowCustomNotification("Espera", $"Procesando texto con {Opciones.Instance.nombreDeLLM()}...");
            IniciarCronometro();
            await ProcessCorreccionWithTimeout();
        }

        private async Task ProcessCorreccionWithTimeout()
        {
            try
            {
                using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(TimeoutSeconds));
                using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(
                    timeoutCts.Token, _cancellationTokenSource.Token);

                var correccionTask = Task.Run(async () =>
                {
                    try
                    {
                        GTP.Log.Log("Iniciando corrección de texto");
                        await GTP.CorregirTexto();
                        GTP.Log.Log("Corrección de texto completada");
                    }
                    catch (Exception ex)
                    {
                        GTP.Log.Log($"Error durante la corrección: {ex.Message}");
                        throw;
                    }
                }, linkedCts.Token);

                await correccionTask;

                await Dispatcher.InvokeAsync(async () =>
                {
                    try
                    {
                        GTP.Log.Log("Procesando resultado de la corrección");
                        CorreccionFinalizada = true;
                        DetenerCronometro();

                        if (GTP.TextoCorregido != null)
                        {
                            GTP.Log.Log("Copiando texto corregido al portapapeles");
                            await ClipboardHelper.SetText(GTP.TextoCorregido);
                            ShowCustomNotification("Se puede pegar",
                                $"Corrección en: {Math.Round(stopwatch.ElapsedMilliseconds / 1000.0, 1)} s");

                            if (Opciones.Instance.modo == Opciones.modoDeUso.Corregir || Opciones.Instance.modo == Opciones.modoDeUso.Ortografia || 
                            Opciones.Instance.modo == Opciones.modoDeUso.Traducir_a_Espanol || Opciones.Instance.modo == Opciones.modoDeUso.Traducir_a_Ingles ||
                            Opciones.Instance.modo == Opciones.modoDeUso.Traducir_a_Italiano || Opciones.Instance.modo == Opciones.modoDeUso.Traducir_a_Portugues)
                            {
                                if (Opciones.Instance.FuncionesOpcionales == Opciones.funcionesOpcionales.MostrarPopUp)
                                {
                                    GTP.Log.Log("Mostrando ventana de resultado");
                                    var resultadoWindow = new VentanaResultado(GTP.TextoCorregido);
                                    resultadoWindow.Show();
                                    await Task.Delay(1000);
                                }
                                else
                                {
                                    GTP.Log.Log("Ejecutando pegado automático");
                                    await pasteLogic.RestoreAndSimulatePaste();
                                }
                            }
                        }
                        else
                        {
                            GTP.Log.Log("Error: TextoCorregido es null");
                            ShowCustomNotification("Error", "No se pudo obtener el texto corregido");
                        }
                    }
                    catch (Exception ex)
                    {
                        GTP.Log.Log($"Error en el procesamiento final: {ex.Message}");
                        ShowCustomNotification("Error", "Error al procesar el resultado");
                    }
                    finally
                    {
                        GTP.Log.Log("Cerrando aplicación");
                        Application.Current.Shutdown();
                    }
                });
            }
            catch (OperationCanceledException)
            {
                GTP.Log.Log("Operación cancelada por timeout");
                await Dispatcher.InvokeAsync(() =>
                {
                    ShowCustomNotification("Error", "La operación excedió el tiempo límite");
                    Application.Current.Shutdown();
                });
            }
            catch (Exception ex)
            {
                GTP.Log.Log($"Error no controlado: {ex.Message}");
                await Dispatcher.InvokeAsync(() =>
                {
                    ShowCustomNotification("Error", "Se produjo un error inesperado");
                    Application.Current.Shutdown();
                });
            }
        }

        protected override void OnExit(ExitEventArgs e)
        {
            _cancellationTokenSource?.Cancel();
            _cancellationTokenSource?.Dispose();
            base.OnExit(e);
        }

        private void ShowCustomNotification(string title, string message)
        {
            try
            {
                GTP.Log.Log($"Mostrando notificación: {title} - {message}");
                if (notificationWindow == null)
                {
                    notificationWindow = new notificacion();
                    notificationWindow.Show();
                }
                notificationWindow.UpdateNotification(title, message);
            }
            catch (Exception ex)
            {
                GTP.Log.Log($"Error al mostrar notificación: {ex.Message}");
            }
        }

        private void IniciarCronometro()
        {
            timer = new System.Windows.Forms.Timer();
            timer.Interval = 100;
            timer.Tick += ActualizarCronometro;
            timer.Start();
            GTP.Log.Log("Cronómetro iniciado");
        }

        private void ActualizarCronometro(object sender, EventArgs e)
        {
            if (!CorreccionFinalizada)
            {
                ShowCustomNotification(
                    $"{Opciones.Instance.nombreDeLLM()} Trabajando..",
                    $"Texto en {GTP.IdiomaDetectado} pasados: {Math.Round(stopwatch.ElapsedMilliseconds / 1000.0, 1)} s"
                );
            }
        }

        private void DetenerCronometro()
        {
            if (timer != null)
            {
                timer.Stop();
                timer.Dispose();
                GTP.Log.Log("Cronómetro detenido");
            }
        }
    }

}