using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
using AxCopilot.Services;

namespace AxCopilot.Views;

public partial class LauncherWindow
{
    // ─── 무지개 글로우 상시 애니메이션 ────────────────────────────────────────

    /// <summary>선택 아이템 상시 무지개 글로우 효과를 적용하거나 제거합니다.</summary>
    private void UpdateSelectionGlow()
    {
        if (_vm.EnableSelectionGlow)
        {
            var gs = new System.Windows.Media.GradientStopCollection
            {
                new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromRgb(0xFF, 0x6B, 0x6B), 0.00),
                new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromRgb(0xFE, 0xCA, 0x57), 0.17),
                new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromRgb(0x48, 0xDB, 0xFB), 0.33),
                new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromRgb(0xFF, 0x9F, 0xF3), 0.50),
                new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromRgb(0x54, 0xA0, 0xFF), 0.67),
                new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromRgb(0x5F, 0x27, 0xCD), 0.83),
                new System.Windows.Media.GradientStop(System.Windows.Media.Color.FromRgb(0xFF, 0x6B, 0x6B), 1.00),
            };
            Resources["SelectionGlowBrush"] = new System.Windows.Media.LinearGradientBrush(
                gs,
                new System.Windows.Point(0, 0),
                new System.Windows.Point(1, 1));
            Resources["SelectionGlowVisibility"] = Visibility.Visible;
        }
        else
        {
            Resources["SelectionGlowBrush"]      = System.Windows.Media.Brushes.Transparent;
            Resources["SelectionGlowVisibility"] = Visibility.Collapsed;
        }
    }

    /// <summary>무지개 글로우를 정지하고 숨깁니다.</summary>
    private void StopRainbowGlow()
    {
        _rainbowTimer?.Stop();
        _rainbowTimer = null;
        if (RainbowGlowBorder != null) RainbowGlowBorder.Opacity = 0;
    }

    /// <summary>런처 테두리 무지개 그라데이션 회전을 시작합니다.</summary>
    private void StartRainbowGlow()
    {
        _rainbowTimer?.Stop();
        if (LauncherRainbowBrush == null || RainbowGlowBorder == null) return;

        _rainbowTimer = new System.Windows.Threading.DispatcherTimer
        {
            Interval = TimeSpan.FromMilliseconds(20)
        };
        var startTime = DateTime.UtcNow;
        _rainbowTimer.Tick += (_, _) =>
        {
            if (!IsVisible) { _rainbowTimer?.Stop(); return; }
            var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds;
            var shift = (elapsed / 2000.0) % 1.0; // 2초에 1바퀴 (느리게)
            var angle = shift * Math.PI * 2;
            LauncherRainbowBrush.StartPoint = new Point(0.5 + 0.5 * Math.Cos(angle), 0.5 + 0.5 * Math.Sin(angle));
            LauncherRainbowBrush.EndPoint = new Point(0.5 - 0.5 * Math.Cos(angle), 0.5 - 0.5 * Math.Sin(angle));
        };
        _rainbowTimer.Start();
    }

    // ─── 애니메이션 헬퍼 ──────────────────────────────────────────────────────

    private static KeyTime KT(double sec) => KeyTime.FromTimeSpan(TimeSpan.FromSeconds(sec));

    private static void AddOpacityPulse(Storyboard sb, UIElement target, int index, double totalSec)
    {
        var a = new DoubleAnimationUsingKeyFrames();
        a.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(index)));
        a.KeyFrames.Add(new LinearDoubleKeyFrame(0.25, KT(index + 0.5)));
        a.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(index + 1)));
        a.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(totalSec)));
        Storyboard.SetTarget(a, target);
        Storyboard.SetTargetProperty(a, new PropertyPath(UIElement.OpacityProperty));
        sb.Children.Add(a);
    }

    private static void AddGroupFlash(Storyboard sb, UIElement[] group, double startSec, double totalSec)
    {
        foreach (var p in group)
        {
            var a = new DoubleAnimationUsingKeyFrames();
            a.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(0)));
            a.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(startSec)));
            a.KeyFrames.Add(new LinearDoubleKeyFrame(0.2, KT(startSec + 0.6)));
            a.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(startSec + 1.2)));
            a.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(totalSec)));
            Storyboard.SetTarget(a, p);
            Storyboard.SetTargetProperty(a, new PropertyPath(UIElement.OpacityProperty));
            sb.Children.Add(a);
        }
    }

    private static DoubleAnimationUsingKeyFrames MakeKeyFrameAnim((double val, double sec)[] frames)
    {
        var a = new DoubleAnimationUsingKeyFrames();
        foreach (var (val, sec) in frames)
            a.KeyFrames.Add(new LinearDoubleKeyFrame(val, KT(sec)));
        return a;
    }

    // ─── 화면 배치 (Phase L3-7: 다중 디스플레이 지원) ────────────────────────

    /// <summary>
    /// 마우스 커서가 위치한 모니터 중앙에 런처를 배치합니다.
    /// RememberPosition 설정이 켜진 경우 마지막 위치를 복원합니다.
    /// </summary>
    private void CenterOnScreen()
    {
        // 위치 기억 기능: 저장된 위치 복원
        var app = System.Windows.Application.Current as App;
        var launcher = app?.SettingsService?.Settings.Launcher;
        if (launcher?.RememberPosition == true && launcher.LastLeft >= 0 && launcher.LastTop >= 0)
        {
            var wa = GetCurrentMonitorWorkArea();
            var w = ActualWidth > 0 ? ActualWidth : 640;
            var h = ActualHeight > 0 ? ActualHeight : 80;
            Left = Math.Clamp(launcher.LastLeft, wa.Left, Math.Max(wa.Left, wa.Right - w));
            Top  = Math.Clamp(launcher.LastTop,  wa.Top,  Math.Max(wa.Top,  wa.Bottom - h));
            return;
        }

        var area = GetCurrentMonitorWorkArea();
        // ActualHeight/ActualWidth는 첫 Show() 전 레이아웃 패스 이전에 0일 수 있음 → 기본값으로 보호
        var w2 = ActualWidth  > 0 ? ActualWidth  : 640;
        var h2 = ActualHeight > 0 ? ActualHeight : 80;
        Left = (area.Width - w2) / 2 + area.Left;
        Top = _vm.WindowPosition switch
        {
            "center" => (area.Height - h2) / 2 + area.Top,
            "bottom" => area.Height * 0.75 + area.Top,
            _        => area.Height * 0.2 + area.Top,  // "center-top" (기본)
        };
    }

    /// <summary>
    /// 마우스 커서가 있는 모니터의 작업 영역을 WPF 논리 좌표(DIP)로 반환합니다.
    /// PresentationSource를 통해 DPI 스케일을 정확하게 보정합니다.
    /// </summary>
    private System.Windows.Rect GetCurrentMonitorWorkArea()
    {
        try
        {
            // 마우스 커서 물리적 좌표 → 해당 모니터 탐색
            var cursorPos = System.Windows.Forms.Cursor.Position;
            var screen    = System.Windows.Forms.Screen.FromPoint(cursorPos);
            var wa        = screen.WorkingArea;  // 물리적 픽셀 단위

            // 물리적 픽셀 → WPF DIP 변환 (DPI 보정)
            var src = PresentationSource.FromVisual(this);
            if (src?.CompositionTarget != null)
            {
                var m  = src.CompositionTarget.TransformFromDevice;  // physical→logical
                var tl = m.Transform(new System.Windows.Point(wa.Left,  wa.Top));
                var br = m.Transform(new System.Windows.Point(wa.Right, wa.Bottom));
                return new System.Windows.Rect(tl, br);
            }
        }
        catch (Exception ex)
        {
            LogService.Warn($"[MultiMonitor] 모니터 감지 실패, 기본 모니터 사용: {ex.Message}");
        }

        // 폴백: WPF 기본 주 모니터
        return SystemParameters.WorkArea;
    }

    // ─── 등장 애니메이션 ──────────────────────────────────────────────────────

    private void AnimateIn()
    {
        Opacity = 0;

        var ease = new CubicEase { EasingMode = EasingMode.EaseOut };

        var fadeAnim = new DoubleAnimation(0, 1,
            TimeSpan.FromMilliseconds(100)) { EasingFunction = ease };

        var slideAnim = new DoubleAnimation(-8, 0,
            TimeSpan.FromMilliseconds(120)) { EasingFunction = ease };

        BeginAnimation(OpacityProperty, fadeAnim);

        // Window에 AllowsTransparency=True 일 때 RenderTransform을 Window에 직접 설정하면
        // InvalidOperationException 발생 → Content(루트 Border)에 적용
        if (Content is System.Windows.FrameworkElement root)
        {
            var translate = new TranslateTransform(0, -10);
            root.RenderTransform = translate;
            root.RenderTransformOrigin = new System.Windows.Point(0.5, 0);
            translate.BeginAnimation(TranslateTransform.YProperty, slideAnim);
        }
    }
}
