using System.Drawing;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.IO;

namespace AxCopilot.Views;

/// <summary>
/// 전체 화면 위에 반투명 오버레이를 표시하고 마우스 드래그로 캡처 영역을 선택합니다.
/// ShowDialog() 후 SelectedRect로 결과를 얻습니다.
/// </summary>
public partial class RegionSelectWindow : Window
{
    public System.Drawing.Rectangle? SelectedRect { get; private set; }

    private readonly System.Drawing.Rectangle _screenBounds;
    private System.Windows.Point _startPoint;
    private System.Windows.Point _endPoint;
    private bool _isDragging;

    public RegionSelectWindow(Bitmap fullScreenshot, System.Drawing.Rectangle screenBounds)
    {
        InitializeComponent();

        _screenBounds = screenBounds;

        // 창을 모든 모니터 전체에 걸쳐 표시
        Left   = screenBounds.X;
        Top    = screenBounds.Y;
        Width  = screenBounds.Width;
        Height = screenBounds.Height;

        // 전체 화면 스크린샷을 배경으로 렌더링
        RootCanvas.Background = CreateFrozenBrush(fullScreenshot);

        // 오버레이 초기 크기 설정
        OverlayTop.Width    = screenBounds.Width;
        OverlayTop.Height   = screenBounds.Height;
        OverlayBottom.Width = screenBounds.Width;
        OverlayLeft.Width   = 0;
        OverlayRight.Width  = 0;

        // 가이드 텍스트 중앙 배치 (Loaded 이후)
        Loaded += (_, _) =>
        {
            Canvas.SetLeft(GuideText, (Width - GuideText.ActualWidth) / 2);
            Canvas.SetTop(GuideText, (Height - GuideText.ActualHeight) / 2);
        };
    }

    private static ImageBrush CreateFrozenBrush(Bitmap bmp)
    {
        using var ms = new MemoryStream();
        bmp.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp);
        ms.Position = 0;
        var img = new BitmapImage();
        img.BeginInit();
        img.StreamSource = ms;
        img.CacheOption  = BitmapCacheOption.OnLoad;
        img.EndInit();
        img.Freeze();
        var brush = new ImageBrush(img) { Stretch = Stretch.None, AlignmentX = AlignmentX.Left, AlignmentY = AlignmentY.Top };
        brush.Freeze();
        return brush;
    }

    private void Window_MouseDown(object sender, MouseButtonEventArgs e)
    {
        if (e.ChangedButton != MouseButton.Left) return;
        _startPoint = e.GetPosition(RootCanvas);
        _isDragging = true;
        GuideText.Visibility = Visibility.Collapsed;
        SelectionBorder.Visibility = Visibility.Visible;
        SizeLabel.Visibility = Visibility.Visible;
        CaptureMouse();
    }

    private void Window_MouseMove(object sender, MouseEventArgs e)
    {
        if (!_isDragging) return;
        var cur = e.GetPosition(RootCanvas);
        UpdateSelection(_startPoint, cur);
    }

    private void Window_MouseUp(object sender, MouseButtonEventArgs e)
    {
        if (!_isDragging || e.ChangedButton != MouseButton.Left) return;
        _isDragging = false;
        ReleaseMouseCapture();

        var cur = e.GetPosition(RootCanvas);
        _endPoint = cur;
        var rect = MakeRect(_startPoint, cur);

        if (rect.Width < 4 || rect.Height < 4)
        {
            // 너무 작으면 무시, 다시 드래그 가능
            return;
        }

        // 선택 완료 — 화살표 키로 미세 조정 후 Enter/더블클릭으로 확정, Esc로 취소
        // SizeLabel 하단에 힌트 표시
        SizeLabelText.Text += "  ·  ↑↓←→ 미세조정  ·  Enter 확정";
    }

    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Escape)
        {
            SelectedRect = null;
            Close();
            return;
        }

        // 드래그 완료 후 화살표 키로 선택 영역 미세 조정
        if (!_isDragging && SelectionBorder.Visibility == Visibility.Visible)
        {
            double dx = 0, dy = 0;
            bool shift = Keyboard.Modifiers.HasFlag(ModifierKeys.Shift);
            double step = shift ? 10 : 1; // Shift 누르면 10px 단위

            switch (e.Key)
            {
                case Key.Left:  dx = -step; break;
                case Key.Right: dx = step;  break;
                case Key.Up:    dy = -step; break;
                case Key.Down:  dy = step;  break;
                case Key.Enter:
                    // Enter 키로 현재 선택 확정
                    var r = MakeRect(_startPoint, _endPoint);
                    if (r.Width >= 4 && r.Height >= 4)
                    {
                        var dpi = VisualTreeHelper.GetDpi(this);
                        SelectedRect = new System.Drawing.Rectangle(
                            (int)(r.X * dpi.DpiScaleX) + _screenBounds.X,
                            (int)(r.Y * dpi.DpiScaleY) + _screenBounds.Y,
                            (int)(r.Width  * dpi.DpiScaleX),
                            (int)(r.Height * dpi.DpiScaleY));
                    }
                    Close();
                    return;
                default: return;
            }

            _endPoint = new System.Windows.Point(_endPoint.X + dx, _endPoint.Y + dy);
            UpdateSelection(_startPoint, _endPoint);
            e.Handled = true;
        }
    }

    private void UpdateSelection(System.Windows.Point a, System.Windows.Point b)
    {
        var rect = MakeRect(a, b);

        Canvas.SetLeft(SelectionBorder, rect.X);
        Canvas.SetTop(SelectionBorder,  rect.Y);
        SelectionBorder.Width  = rect.Width;
        SelectionBorder.Height = rect.Height;

        // 바깥 마스크 업데이트
        OverlayTop.Width  = Width;
        OverlayTop.Height = rect.Y;

        OverlayBottom.Width  = Width;
        OverlayBottom.Height = Height - rect.Y - rect.Height;
        Canvas.SetTop(OverlayBottom, rect.Y + rect.Height);

        OverlayLeft.Width  = rect.X;
        OverlayLeft.Height = rect.Height;
        Canvas.SetTop(OverlayLeft, rect.Y);

        OverlayRight.Width  = Width - rect.X - rect.Width;
        OverlayRight.Height = rect.Height;
        Canvas.SetLeft(OverlayRight, rect.X + rect.Width);
        Canvas.SetTop(OverlayRight,  rect.Y);

        // 크기 레이블
        var dpiScale = VisualTreeHelper.GetDpi(this);
        var pw = (int)(rect.Width  * dpiScale.DpiScaleX);
        var ph = (int)(rect.Height * dpiScale.DpiScaleY);
        SizeLabelText.Text = $"{pw} × {ph}";
        Canvas.SetLeft(SizeLabel, rect.X + rect.Width + 8);
        Canvas.SetTop(SizeLabel,  rect.Y + rect.Height + 4);
    }

    private static Rect MakeRect(System.Windows.Point a, System.Windows.Point b) =>
        new(Math.Min(a.X, b.X), Math.Min(a.Y, b.Y),
            Math.Abs(b.X - a.X), Math.Abs(b.Y - a.Y));
}
