using System;
using System.IO;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Controls;
using System.Windows.Shapes;
using Tesseract;
using System.Threading.Tasks;
using Point = System.Windows.Point;
using Rect = System.Windows.Rect;
using Size = System.Windows.Size;
using Brushes = System.Windows.Media.Brushes;
using Cursors = System.Windows.Input.Cursors;
using Cursor = System.Windows.Input.Cursor;
using Color = System.Windows.Media.Color;
using Path = System.IO.Path;
using MessageBox = System.Windows.MessageBox;
using MouseEventArgs = System.Windows.Input.MouseEventArgs;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using Rectangle = System.Windows.Shapes.Rectangle; 

namespace GTPCorrgir
{
    public class ScreenCaptureWindow : Window
    {
        private Point startPoint;
        private Point currentPoint;
        private bool hasFirstPoint;
        private System.Windows.Shapes.Rectangle selectionRectangle;
        private Canvas overlayCanvas;
        private readonly Cursor crosshairCursor = Cursors.Cross;
        private Window overlayWindow;
        private System.Windows.Forms.Screen targetScreen; // Añadimos esta referencia

        public ScreenCaptureWindow()
        {
            InitializeInitialWindow();
        }

        private void InitializeInitialWindow()
        {
            // Calcular el rectángulo virtual que engloba todas las pantallas
            var allScreens = System.Windows.Forms.Screen.AllScreens;
            int minX = allScreens.Min(s => s.Bounds.Left);
            int minY = allScreens.Min(s => s.Bounds.Top);
            int maxX = allScreens.Max(s => s.Bounds.Right);
            int maxY = allScreens.Max(s => s.Bounds.Bottom);

            // Configurar la ventana inicial para cubrir todas las pantallas
            this.WindowStyle = WindowStyle.None;
            this.ResizeMode = ResizeMode.NoResize;
            this.Width = maxX - minX;
            this.Height = maxY - minY;
            this.Left = minX;
            this.Top = minY;
            this.AllowsTransparency = true;
            this.Background = new SolidColorBrush(Color.FromArgb(0, 0, 0, 0));
            this.ShowInTaskbar = false;
            this.Topmost = true;
            this.Cursor = crosshairCursor;

            // Añadir un panel transparente que cubra toda la ventana
            var panel = new Grid
            {
                Background = new SolidColorBrush(Color.FromArgb(1, 0, 0, 0))
            };
            this.Content = panel;

            // Agregar el evento del primer clic
            this.MouseLeftButtonDown += InitialWindow_MouseLeftButtonDown;
        }

        private void InitialWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // Obtener la pantalla donde se hizo clic
            var clickPoint = PointToScreen(e.GetPosition(this));
            Console.WriteLine($"Click point screen coords: X={clickPoint.X}, Y={clickPoint.Y}");

            targetScreen = System.Windows.Forms.Screen.FromPoint(
                new System.Drawing.Point((int)clickPoint.X, (int)clickPoint.Y));

            Console.WriteLine($"Target screen bounds: Left={targetScreen.Bounds.Left}, Top={targetScreen.Bounds.Top}, Right={targetScreen.Bounds.Right}, Bottom={targetScreen.Bounds.Bottom}");

            // Remover este evento ya que solo lo necesitamos una vez
            this.MouseLeftButtonDown -= InitialWindow_MouseLeftButtonDown;

            // Calcular el punto relativo a la pantalla objetivo
            startPoint = new Point(
                clickPoint.X - targetScreen.Bounds.Left,
                clickPoint.Y - targetScreen.Bounds.Top
            );

            Console.WriteLine($"Start point relative coords: X={startPoint.X}, Y={startPoint.Y}");

            // Inicializar la ventana de overlay ANTES de posicionar el rectángulo
            InitializeOverlayWindow(targetScreen);

            // Asegurarse que el overlay esté completamente inicializado
            overlayWindow.Dispatcher.Invoke(() =>
            {
                selectionRectangle.Visibility = Visibility.Visible;
                Canvas.SetLeft(selectionRectangle, startPoint.X);
                Canvas.SetTop(selectionRectangle, startPoint.Y);
                selectionRectangle.Width = 0;
                selectionRectangle.Height = 0;
                hasFirstPoint = true;
            });
        }

        private void InitializeOverlayWindow(System.Windows.Forms.Screen screen)
        {
            overlayWindow = new Window
            {
                WindowStyle = WindowStyle.None,
                ResizeMode = ResizeMode.NoResize,
                AllowsTransparency = true,
                Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0)),
                Topmost = true,
                ShowInTaskbar = false,
                Width = screen.Bounds.Width,
                Height = screen.Bounds.Height,
                WindowStartupLocation = WindowStartupLocation.Manual,
                Left = screen.Bounds.Left,
                Top = screen.Bounds.Top
            };

            InitializeComponents(overlayWindow);
            SetupEventHandlers();

            overlayWindow.Show();
            overlayWindow.Activate(); // Asegurar que la ventana tiene el foco
            this.Hide();
        }

        private void InitializeComponents(Window window)
        {
            overlayCanvas = new Canvas
            {
                HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch,
                VerticalAlignment = System.Windows.VerticalAlignment.Stretch
            };

            var grid = new Grid();
            grid.Children.Add(overlayCanvas);
            window.Content = grid;

            selectionRectangle = new System.Windows.Shapes.Rectangle
            {
                Stroke = new SolidColorBrush(Colors.Red),
                StrokeThickness = 2,
                Fill = new SolidColorBrush(Color.FromArgb(50, 255, 255, 255)),
                Visibility = Visibility.Collapsed
            };

            overlayCanvas.Children.Add(selectionRectangle);
        }

        private void SetupEventHandlers()
        {
            overlayWindow.MouseLeftButtonDown += OverlaySecondPoint_MouseLeftButtonDown;
            overlayWindow.MouseMove += OverlayCanvas_MouseMove;
            overlayWindow.KeyDown += MainWindow_KeyDown;
        }

        private void OverlayCanvas_MouseMove(object sender, MouseEventArgs e)
        {
            if (!hasFirstPoint) return;

            currentPoint = e.GetPosition(overlayCanvas);
            UpdateSelectionRectangle(startPoint, currentPoint);
        }

        private void OverlaySecondPoint_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!hasFirstPoint) return;

            // Capturar el segundo punto
            var endPoint = e.GetPosition(overlayCanvas);

            // Validar el tamaño del rectángulo
            double width = Math.Abs(endPoint.X - startPoint.X);
            double height = Math.Abs(endPoint.Y - startPoint.Y);

            // Validar tamaño mínimo (5x5 pixels)
            const double MIN_SIZE = 5.0;
            if (width < MIN_SIZE || height < MIN_SIZE)
            {
                selectionRectangle.Visibility = Visibility.Collapsed;
                var notification = new notificacion();
                notification.UpdateNotification("Selección muy pequeña",
                    "Por favor, seleccione un área más grande (mínimo 5x5 píxeles)");
                notification.Show();
                hasFirstPoint = false;
                return;
            }

            // Ocultar el rectángulo inmediatamente
            selectionRectangle.Visibility = Visibility.Collapsed;

            // Mostrar notificación de procesamiento
            var processingNotification = new notificacion();
            processingNotification.UpdateNotification("Procesando", "Analizando imagen seleccionada...");
            processingNotification.Show();

            // Si las validaciones pasan, proceder con la captura
            CaptureAndProcessArea();
        }

        private void UpdateSelectionRectangle(Point start, Point current)
        {
            double x = Math.Min(start.X, current.X);
            double y = Math.Min(start.Y, current.Y);
            double width = Math.Abs(current.X - start.X);
            double height = Math.Abs(current.Y - start.Y);

            Canvas.SetLeft(selectionRectangle, x);
            Canvas.SetTop(selectionRectangle, y);
            selectionRectangle.Width = width;
            selectionRectangle.Height = height;
        }

        private void MainWindow_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                overlayWindow?.Close();
                this.Close();
            }
        }

        private string GetTesseractExecutablePath()
        {
            string baseDir = AppDomain.CurrentDomain.BaseDirectory;
            string tessDataDir = Path.Combine(baseDir, "tessdata");

            if (!Directory.Exists(tessDataDir))
            {
                throw new DirectoryNotFoundException(
                    $"No se encontró el directorio tessdata en {tessDataDir}. " +
                    "Asegúrate de que la carpeta tessdata existe y contiene los archivos de entrenamiento.");
            }

            return tessDataDir;
        }

        private BitmapSource CaptureScreen(double x, double y, double width, double height)
        {
            try
            {
                // Usar la referencia guardada del screen objetivo
                var screenPoint = new System.Drawing.Point(
                    (int)(targetScreen.Bounds.Left + x),
                    (int)(targetScreen.Bounds.Top + y)
                );

                Console.WriteLine($"Capture coordinates: X={screenPoint.X}, Y={screenPoint.Y}, Width={width}, Height={height}");

                using (var screenBmp = new System.Drawing.Bitmap(
                    (int)width,
                    (int)height,
                    System.Drawing.Imaging.PixelFormat.Format32bppArgb))
                {
                    using (var bmpGraphics = System.Drawing.Graphics.FromImage(screenBmp))
                    {
                        bmpGraphics.CopyFromScreen(
                            screenPoint.X,
                            screenPoint.Y,
                            0,
                            0,
                            new System.Drawing.Size((int)width, (int)height)
                        );
                    }

                    using (var memory = new MemoryStream())
                    {
                        screenBmp.Save(memory, System.Drawing.Imaging.ImageFormat.Png);
                        memory.Position = 0;

                        var bitmapImage = new BitmapImage();
                        bitmapImage.BeginInit();
                        bitmapImage.StreamSource = memory;
                        bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
                        bitmapImage.EndInit();
                        bitmapImage.Freeze();

                        return bitmapImage;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error al capturar pantalla: {ex.Message}");
                return null;
            }
        }

        private async void CaptureAndProcessArea()
        {
            try
            {
                this.Hide();
                await Task.Delay(100);

                double x = Canvas.GetLeft(selectionRectangle);
                double y = Canvas.GetTop(selectionRectangle);
                double width = selectionRectangle.Width;
                double height = selectionRectangle.Height;

                var screenCapture = CaptureScreen(x, y, width, height);
                if (screenCapture == null) return;

                var screenBitmap = new RenderTargetBitmap(
                    (int)width,
                    (int)height,
                    96, 96,
                    PixelFormats.Pbgra32);

                var visual = new DrawingVisual();
                using (var context = visual.RenderOpen())
                {
                    context.DrawImage(screenCapture, new Rect(0, 0, width, height));
                }
                screenBitmap.Render(visual);

                var encoder = new PngBitmapEncoder();
                encoder.Frames.Add(BitmapFrame.Create(screenBitmap));

                using (var memoryStream = new MemoryStream())
                {
                    encoder.Save(memoryStream);
                    memoryStream.Position = 0;

                    string tesseractPath = GetTesseractExecutablePath();
                    using (var engine = new TesseractEngine(tesseractPath, "eng", EngineMode.Default))
                    {
                        engine.SetVariable("tessedit_char_whitelist", " ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-.");

                        using (var img = Pix.LoadFromMemory(memoryStream.ToArray()))
                        {
                            var result = engine.Process(img);
                            string ocrText = result.GetText();

                            using (var textProcessor = new OcrTextProcessor())
                            {
                                string processedText = await textProcessor.ProcessOcrText(ocrText);
                                var notificationWindow = new notificacion();
                                notificationWindow.UpdateNotification("OCR Completado", "Texto copiado al portapapeles");
                                notificationWindow.Show();
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Error processing capture: {ex.Message}",
                              "Error", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                overlayWindow?.Close();
                this.Close();
            }
        }
    }
}