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;
using System.Windows.Data;
using Binding = System.Windows.Data.Binding;
using Image = System.Windows.Controls.Image;

namespace GTPCorrgir
{
    public class ScreenCaptureWindow : Window
    {
        private Point startPoint;
        private Point currentPoint;
        private bool hasFirstPoint;
        private Rectangle selectionRectangle;
        private Canvas overlayCanvas;
        private readonly Cursor crosshairCursor = Cursors.Cross;
        private bool isSelecting;
        private TextBlock dimensionsText;

        public ScreenCaptureWindow()
        {
            InitializeOverlayWindow();
        }

        private void InitializeOverlayWindow()
        {
            // Calcular el rectángulo virtual que engloba todas las pantallas
            var virtualScreen = GetVirtualScreenBounds();

            // Configurar la ventana principal
            this.WindowStyle = WindowStyle.None;
            this.ResizeMode = ResizeMode.NoResize;
            this.AllowsTransparency = true;
            this.Background = new SolidColorBrush(Color.FromArgb(128, 0, 0, 0));
            this.ShowInTaskbar = false;
            this.Topmost = true;
            this.Cursor = crosshairCursor;

            // Establecer la posición y tamaño para cubrir todas las pantallas
            this.Left = virtualScreen.Left;
            this.Top = virtualScreen.Top;
            this.Width = virtualScreen.Width;
            this.Height = virtualScreen.Height;

            InitializeComponents();
            SetupEventHandlers();
        }

        private System.Drawing.Rectangle GetVirtualScreenBounds()
        {
            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);

            return new System.Drawing.Rectangle(minX, minY, maxX - minX, maxY - minY);
        }

        private void InitializeComponents()
        {
            overlayCanvas = new Canvas();

            // Obtener el área virtual que engloba todas las pantallas
            var virtualScreen = GetVirtualScreenBounds();

            // Capturar toda el área de pantallas
            var screenBitmap = CaptureScreen(virtualScreen.Left, virtualScreen.Top, virtualScreen.Width, virtualScreen.Height);

            // Crear imagen con la captura
            var screenImage = new Image
            {
                Source = screenBitmap,
                Width = virtualScreen.Width,
                Height = virtualScreen.Height,
                Opacity = 0.3  // Esto oscurece toda la imagen
            };

            // Crear imagen para el área seleccionada (la misma captura pero opacidad normal)
            var selectionImage = new Image
            {
                Source = screenBitmap,
                Width = virtualScreen.Width,
                Height = virtualScreen.Height,
                Opacity = 1
            };

            // Crear el clip para la imagen de selección
            var clipRectangle = new RectangleGeometry();
            selectionImage.Clip = clipRectangle;
            selectionImage.Visibility = Visibility.Collapsed;

            // Rectángulo de selección (solo el borde)
            selectionRectangle = new Rectangle
            {
                Stroke = new SolidColorBrush(Color.FromRgb(120, 255, 120)),
                StrokeThickness = 1.5,
                Fill = Brushes.Transparent,
                Visibility = Visibility.Collapsed
            };

            // Agregar todos los elementos al canvas
            overlayCanvas.Children.Add(screenImage);
            overlayCanvas.Children.Add(selectionImage);
            overlayCanvas.Children.Add(selectionRectangle);

            // Actualizar el clip cuando se mueve el rectángulo
            selectionRectangle.LayoutUpdated += (s, e) =>
            {
                if (selectionRectangle.Visibility == Visibility.Visible)
                {
                    selectionImage.Visibility = Visibility.Visible;
                    clipRectangle.Rect = new Rect(
                        Canvas.GetLeft(selectionRectangle),
                        Canvas.GetTop(selectionRectangle),
                        selectionRectangle.Width,
                        selectionRectangle.Height
                    );
                }
                else
                {
                    selectionImage.Visibility = Visibility.Collapsed;
                }
            };

            this.Content = overlayCanvas;
        }

        private void UpdateSelectionRectangle(Point start, Point current)
        {
            double left = Math.Min(start.X, current.X);
            double top = 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, left);
            Canvas.SetTop(selectionRectangle, top);
            selectionRectangle.Width = width;
            selectionRectangle.Height = height;
        }

        private void SetupEventHandlers()
        {
            this.MouseLeftButtonDown += Overlay_MouseLeftButtonDown;
            this.MouseLeftButtonUp += Overlay_MouseLeftButtonUp;
            this.MouseMove += Overlay_MouseMove;
            this.KeyDown += Window_KeyDown;
        }

        private void Overlay_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!hasFirstPoint)
            {
                // Primer punto
                startPoint = e.GetPosition(overlayCanvas);
                hasFirstPoint = true;
                isSelecting = true;

                selectionRectangle.Visibility = Visibility.Visible;
                UpdateSelectionRectangle(startPoint, startPoint);
            }
        }

        private void Overlay_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (hasFirstPoint && isSelecting)
            {
                isSelecting = false;
                currentPoint = e.GetPosition(overlayCanvas);

                double width = Math.Abs(currentPoint.X - startPoint.X);
                double height = Math.Abs(currentPoint.Y - startPoint.Y);

                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;
                }

                selectionRectangle.Visibility = Visibility.Collapsed;
                var processingNotification = new notificacion();
                processingNotification.UpdateNotification("Procesando", "Analizando imagen seleccionada...");
                processingNotification.Show();                

                CaptureAndProcessArea();
            }
        }

        private void Overlay_MouseMove(object sender, MouseEventArgs e)
        {
            if (hasFirstPoint && isSelecting)
            {
                currentPoint = e.GetPosition(overlayCanvas);
                UpdateSelectionRectangle(startPoint, currentPoint);
            }
        }

        private BitmapSource CaptureScreen(double x, double y, double width, double height)
        {
            try
            {
                // Las coordenadas ya están en el espacio de la pantalla virtual
                var screenPoint = new System.Drawing.Point((int)x, (int)y);

                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}");
                Console.WriteLine($"Stack trace: {ex.StackTrace}");
                return null;
            }
        }

        private async void CaptureAndProcessArea()
        {
            try
            {
                double x = Canvas.GetLeft(selectionRectangle);
                double y = Canvas.GetTop(selectionRectangle);
                double width = selectionRectangle.Width;
                double height = selectionRectangle.Height;

                // Ajustar las coordenadas al origen de la pantalla virtual
                x += this.Left;
                y += this.Top;

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

                // Resto del procesamiento OCR igual que antes
                using (var memoryStream = new MemoryStream())
                {
                    var encoder = new PngBitmapEncoder();
                    encoder.Frames.Add(BitmapFrame.Create(screenCapture));
                    encoder.Save(memoryStream);
                    memoryStream.Position = 0;

                    string tesseractPath = GetTesseractExecutablePath();
                    using (var engine = new TesseractEngine(tesseractPath, "eng", EngineMode.Default))
                    {
                        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
            {
                this.Close();
            }
        }

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Escape)
            {
                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;
        }
    }
}