using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Microsoft.Win32;
using AxCopilot.Models;
using AxCopilot.ViewModels;

namespace AxCopilot.Views;

public partial class LauncherWindow : Window
{
    private static App? CurrentApp => System.Windows.Application.Current as App;

    [DllImport("user32.dll")]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll")]
    private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

    [DllImport("user32.dll")]
    private static extern IntPtr GetForegroundWindow();

    [DllImport("user32.dll")]
    private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint processId);

    [DllImport("user32.dll")]
    private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach);

    [DllImport("kernel32.dll")]
    private static extern uint GetCurrentThreadId();

    private readonly LauncherViewModel _vm;
    private System.Windows.Threading.DispatcherTimer? _indexStatusTimer;

    /// <summary>Ctrl+, 단축키로 설정 창을 여는 콜백 (App.xaml.cs에서 주입)</summary>
    public Action? OpenSettingsAction { get; set; }

    public LauncherWindow(LauncherViewModel vm)
    {
        _vm = vm;
        // 테마를 InitializeComponent 전에 적용 → 첫 렌더링부터 올바른 테마 표시 (깜빡임 방지)
        ApplyTheme();
        InitializeComponent();
        DataContext = vm;

        vm.CloseRequested += (_, _) => Hide();
        vm.NotificationRequested += (_, msg) => ShowNotification(msg);

        // Phase L3-9: 위젯 가시성 감지 등록 (Show/Hide에 자동 반응)
        InitWidgets();

        // InputText가 코드에서 변경될 때 커서를 끝으로 이동
        // (F1→"help", Ctrl+B→"fav", Ctrl+D→"cd Downloads" 등 자동 입력 후 위화감 해소)
        vm.PropertyChanged += (_, e) =>
        {
            if (e.PropertyName == nameof(LauncherViewModel.InputText))
            {
                // DispatcherPriority.Input: 바인딩 업데이트가 완료된 직후 실행
                Dispatcher.InvokeAsync(
                    () => { if (InputBox != null) InputBox.CaretIndex = InputBox.Text.Length; },
                    System.Windows.Threading.DispatcherPriority.Input);
            }
        };

        // 인덱싱 완료 시 상태 표시
        var app = (App)System.Windows.Application.Current;
        if (app.IndexService != null)
        {
            app.IndexService.IndexRebuilt += (_, _) =>
            {
                Dispatcher.BeginInvoke(() =>
                {
                    var svc = app.IndexService;
                    IndexStatusText.Text = $"✓ {svc.LastIndexCount:N0}개 항목 색인됨 ({svc.LastIndexDuration.TotalSeconds:F1}초)";
                    IndexStatusText.Visibility = Visibility.Visible;
                    // 기존 타이머 정리 후 5초 후 자동 숨기기
                    _indexStatusTimer?.Stop();
                    _indexStatusTimer = new System.Windows.Threading.DispatcherTimer
                    {
                        Interval = TimeSpan.FromSeconds(5)
                    };
                    _indexStatusTimer.Tick += (_, _) => { IndexStatusText.Visibility = Visibility.Collapsed; _indexStatusTimer.Stop(); };
                    _indexStatusTimer.Start();
                });
            };
        }
    }

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        CenterOnScreen();
        ApplyTheme();
        Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input, () =>
        {
            Activate();
            ForceForeground();
            InputBox.Focus();
            Keyboard.Focus(InputBox);
        });
    }

    private static readonly Random _iconRng = new();
    private System.Windows.Media.Animation.Storyboard? _iconStoryboard;
    private System.Windows.Threading.DispatcherTimer? _rainbowTimer;

    /// <summary>외부에서 입력 텍스트를 설정합니다 (AI 명령 전달용).</summary>
    public void SetInputText(string text)
    {
        if (InputBox == null) return;
        InputBox.Text = text;
        InputBox.CaretIndex = text.Length;
        // 자동 실행
        _vm.InputText = text;
    }

    /// <summary>
    /// 포그라운드 창 전환 제한을 우회하여 확실히 포커스를 가져옵니다.
    /// Windows는 현재 포그라운드 스레드가 아닌 스레드에서 SetForegroundWindow를 차단하므로,
    /// AttachThreadInput으로 일시적으로 스레드를 연결합니다.
    /// </summary>
    private void ForceForeground()
    {
        try
        {
            var hwnd = new WindowInteropHelper(this).Handle;
            if (hwnd == IntPtr.Zero) return;

            var foreHwnd = GetForegroundWindow();
            if (foreHwnd == hwnd) return; // 이미 포그라운드

            uint foreThread = GetWindowThreadProcessId(foreHwnd, out _);
            uint thisThread = GetCurrentThreadId();

            if (foreThread != thisThread)
            {
                AttachThreadInput(thisThread, foreThread, true);
                SetForegroundWindow(hwnd);
                AttachThreadInput(thisThread, foreThread, false);
            }
            else
            {
                SetForegroundWindow(hwnd);
            }
        }
        catch (Exception) { /* 포커스 강제 실패 시 기본 WPF Activate에 의존 */ }
    }

    public new void Show()
    {
        _vm.RefreshPlaceholder();
        _vm.OnShown();
        _vm.InputText = "";
        base.Show();
        CenterOnScreen();
        AnimateIn();

        // 포그라운드 강제 + 포커스를 3단계로 보장
        // 1단계: 즉시 활성화
        Activate();
        ForceForeground();

        // 2단계: 레이아웃 완료 후 포커스
        Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input, () =>
        {
            Activate();
            InputBox.Focus();
            Keyboard.Focus(InputBox);
            InputBox.SelectAll();
        });

        // 3단계: 렌더링 완료 후 최종 포커스 보장 (애니메이션 끝난 뒤)
        Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Loaded, () =>
        {
            if (!InputBox.IsKeyboardFocused)
            {
                ForceForeground();
                InputBox.Focus();
                Keyboard.Focus(InputBox);
            }
        });

        // 런처 테두리 표시 설정
        if (_vm.ShowLauncherBorder)
        {
            MainBorder.BorderThickness = new Thickness(1);
            MainBorder.BorderBrush = (System.Windows.Media.Brush)FindResource("BorderColor");
        }
        else
        {
            MainBorder.BorderThickness = new Thickness(0);
            MainBorder.BorderBrush = System.Windows.Media.Brushes.Transparent;
        }

        if (_vm.EnableIconAnimation)
            ApplyRandomIconAnimation();
        else
            ResetIconAnimation();

        if (_vm.EnableRainbowGlow)
            StartRainbowGlow();
        else
            StopRainbowGlow();

        UpdateSelectionGlow();

        // Phase L3-9: 위젯은 IsVisibleChanged로 자동 제어 (InitWidgets에서 등록)
    }

    /// <summary>아이콘 애니메이션을 중지하고 모든 픽셀을 완전 점등 상태로 복원합니다.</summary>
    private void ResetIconAnimation()
    {
        _iconStoryboard?.Stop();
        _iconStoryboard = null;
        var pixels = new[] { PixelBlue, PixelGreen1, PixelRed, PixelGreen2 };
        foreach (var p in pixels)
        {
            if (p == null) continue;
            p.BeginAnimation(UIElement.OpacityProperty, null);
            p.Opacity = 1;
        }
        if (IconRotate != null) { IconRotate.BeginAnimation(RotateTransform.AngleProperty, null); IconRotate.Angle = 45; }
        if (IconScale != null) { IconScale.BeginAnimation(ScaleTransform.ScaleXProperty, null); IconScale.BeginAnimation(ScaleTransform.ScaleYProperty, null); IconScale.ScaleX = 1; IconScale.ScaleY = 1; }
    }

    /// <summary>10가지 다이아몬드 픽셀 애니메이션 효과 중 랜덤 1개를 적용합니다.</summary>
    private void ApplyRandomIconAnimation()
    {
        _iconStoryboard?.Stop();

        var pixels = new[] { PixelBlue, PixelGreen1, PixelRed, PixelGreen2 };
        if (pixels.Any(p => p == null) || IconRotate == null || IconScale == null) return;

        // 모든 상태 초기화
        foreach (var p in pixels) { p.BeginAnimation(UIElement.OpacityProperty, null); p.Opacity = 1; }
        IconRotate.BeginAnimation(RotateTransform.AngleProperty, null);
        IconScale.BeginAnimation(ScaleTransform.ScaleXProperty, null);
        IconScale.BeginAnimation(ScaleTransform.ScaleYProperty, null);
        IconRotate.Angle = 45;
        IconScale.ScaleX = 1; IconScale.ScaleY = 1;

        var sb = new Storyboard { RepeatBehavior = new RepeatBehavior(3) };
        // 0~9: 기존 효과, 9: 정적(애니 없음), 10~14: 추가 효과, 15~19: 역동적 추가 효과
        int effect = _iconRng.Next(20);

        switch (effect)
        {
            case 0: // 순차 점멸 — 파랑→초록1→빨강→초록2 순서로 깜빡임
                for (int i = 0; i < 4; i++)
                    AddOpacityPulse(sb, pixels[i], i, 4.0);
                break;

            case 1: // 전체 호흡 — 4개 동시에 밝아졌다 어두워짐
                foreach (var p in pixels)
                {
                    var a = new DoubleAnimation(1, 0.35, TimeSpan.FromSeconds(1.5)) { AutoReverse = true };
                    Storyboard.SetTarget(a, p);
                    Storyboard.SetTargetProperty(a, new PropertyPath(UIElement.OpacityProperty));
                    sb.Children.Add(a);
                }
                break;

            case 2: // 대각선 교차 — 좌상+우하 vs 우상+좌하 번갈아 깜빡임
                AddGroupFlash(sb, new[] { pixels[0], pixels[3] }, 0, 3.2);
                AddGroupFlash(sb, new[] { pixels[1], pixels[2] }, 1.6, 3.2);
                break;

            case 3: // 시계방향 순회 점등 — 한 개씩 순서대로 밝아짐
            {
                var order = new[] { pixels[0], pixels[1], pixels[3], pixels[2] };
                for (int i = 0; i < 4; i++)
                {
                    var a = MakeKeyFrameAnim(new (double val, double sec)[] {
                        (0.15, 0), (0.15, i*0.5), (1, i*0.5+0.25), (1, i*0.5+0.7), (0.15, i*0.5+0.95), (0.15, 2.5) });
                    Storyboard.SetTarget(a, order[i]);
                    Storyboard.SetTargetProperty(a, new PropertyPath(UIElement.OpacityProperty));
                    sb.Children.Add(a);
                }
                break;
            }

            case 4: // 💫 천천히 360도 회전 (PPT 회전판 효과) — 다이아몬드 전체가 돌아감
            {
                var rot = new DoubleAnimation(45, 405, TimeSpan.FromSeconds(4))
                    { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
                Storyboard.SetTarget(rot, DiamondIcon);
                Storyboard.SetTargetProperty(rot, new PropertyPath("RenderTransform.Children[0].Angle"));
                sb.Children.Add(rot);
                break;
            }

            case 5: // 💫 펄스 확대/축소 (PPT 강조 효과) — 전체가 커졌다 작아짐
            {
                var sx = new DoubleAnimation(1, 1.25, TimeSpan.FromSeconds(0.6))
                    { AutoReverse = true, EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseInOut } };
                var sy = new DoubleAnimation(1, 1.25, TimeSpan.FromSeconds(0.6))
                    { AutoReverse = true, EasingFunction = new QuadraticEase { EasingMode = EasingMode.EaseInOut } };
                Storyboard.SetTarget(sx, DiamondIcon);
                Storyboard.SetTarget(sy, DiamondIcon);
                Storyboard.SetTargetProperty(sx, new PropertyPath("RenderTransform.Children[1].ScaleX"));
                Storyboard.SetTargetProperty(sy, new PropertyPath("RenderTransform.Children[1].ScaleY"));
                sb.Children.Add(sx);
                sb.Children.Add(sy);
                break;
            }

            case 6: // 💫 바운스 등장 — 작아졌다가 탄력적으로 커짐 (PPT 바운스)
            {
                sb.RepeatBehavior = RepeatBehavior.Forever;
                var bx = new DoubleAnimationUsingKeyFrames();
                bx.KeyFrames.Add(new LinearDoubleKeyFrame(0.7, KT(0)));
                bx.KeyFrames.Add(new EasingDoubleKeyFrame(1.15, KT(0.35), new BounceEase { Bounces = 2, Bounciness = 3 }));
                bx.KeyFrames.Add(new LinearDoubleKeyFrame(1.0, KT(0.6)));
                bx.KeyFrames.Add(new LinearDoubleKeyFrame(1.0, KT(3.0)));
                var by = bx.Clone();
                Storyboard.SetTarget(bx, DiamondIcon);
                Storyboard.SetTarget(by, DiamondIcon);
                Storyboard.SetTargetProperty(bx, new PropertyPath("RenderTransform.Children[1].ScaleX"));
                Storyboard.SetTargetProperty(by, new PropertyPath("RenderTransform.Children[1].ScaleY"));
                sb.Children.Add(bx);
                sb.Children.Add(by);
                break;
            }

            case 7: // 💫 진동 흔들림 (PPT 티터) — 좌우로 살짝 흔들림
            {
                var shake = new DoubleAnimationUsingKeyFrames();
                shake.KeyFrames.Add(new LinearDoubleKeyFrame(45, KT(0)));
                shake.KeyFrames.Add(new LinearDoubleKeyFrame(50, KT(0.08)));
                shake.KeyFrames.Add(new LinearDoubleKeyFrame(40, KT(0.16)));
                shake.KeyFrames.Add(new LinearDoubleKeyFrame(48, KT(0.24)));
                shake.KeyFrames.Add(new LinearDoubleKeyFrame(42, KT(0.32)));
                shake.KeyFrames.Add(new LinearDoubleKeyFrame(45, KT(0.4)));
                shake.KeyFrames.Add(new LinearDoubleKeyFrame(45, KT(3.5)));
                Storyboard.SetTarget(shake, DiamondIcon);
                Storyboard.SetTargetProperty(shake, new PropertyPath("RenderTransform.Children[0].Angle"));
                sb.Children.Add(shake);
                break;
            }

            case 8: // 💫 파도 — 좌측에서 우측으로 순차적으로 확대됐다 복귀
            {
                for (int i = 0; i < 4; i++)
                {
                    var wave = new DoubleAnimationUsingKeyFrames();
                    double d = i * 0.3;
                    wave.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(0)));
                    wave.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(d)));
                    wave.KeyFrames.Add(new EasingDoubleKeyFrame(0.1, KT(d + 0.25),
                        new QuadraticEase { EasingMode = EasingMode.EaseOut }));
                    wave.KeyFrames.Add(new EasingDoubleKeyFrame(1, KT(d + 0.55),
                        new QuadraticEase { EasingMode = EasingMode.EaseIn }));
                    wave.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(3)));
                    Storyboard.SetTarget(wave, pixels[i]);
                    Storyboard.SetTargetProperty(wave, new PropertyPath(UIElement.OpacityProperty));
                    sb.Children.Add(wave);
                }
                break;
            }

            case 9: // 정적 — 완전 점등 상태 (쉬는 턴, 애니메이션 없음)
                foreach (var p in pixels) p.Opacity = 1;
                return;

            case 10: // 💫 역방향 회전 — 반시계 방향으로 천천히 회전
            {
                var rot = new DoubleAnimation(45, -315, TimeSpan.FromSeconds(4.5))
                    { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut } };
                Storyboard.SetTarget(rot, DiamondIcon);
                Storyboard.SetTargetProperty(rot, new PropertyPath("RenderTransform.Children[0].Angle"));
                sb.Children.Add(rot);
                break;
            }

            case 11: // 💫 하트비트 — 짧은 이중 펄스가 규칙적으로 반복
            {
                var hb = new DoubleAnimationUsingKeyFrames();
                hb.KeyFrames.Add(new LinearDoubleKeyFrame(1,    KT(0)));
                hb.KeyFrames.Add(new EasingDoubleKeyFrame(1.3,  KT(0.1),  new QuadraticEase { EasingMode = EasingMode.EaseOut }));
                hb.KeyFrames.Add(new EasingDoubleKeyFrame(1.0,  KT(0.22), new QuadraticEase { EasingMode = EasingMode.EaseIn  }));
                hb.KeyFrames.Add(new EasingDoubleKeyFrame(1.2,  KT(0.32), new QuadraticEase { EasingMode = EasingMode.EaseOut }));
                hb.KeyFrames.Add(new EasingDoubleKeyFrame(1.0,  KT(0.44), new QuadraticEase { EasingMode = EasingMode.EaseIn  }));
                hb.KeyFrames.Add(new LinearDoubleKeyFrame(1.0,  KT(2.8)));
                var hby = hb.Clone();
                Storyboard.SetTarget(hb, DiamondIcon);
                Storyboard.SetTarget(hby, DiamondIcon);
                Storyboard.SetTargetProperty(hb,  new PropertyPath("RenderTransform.Children[1].ScaleX"));
                Storyboard.SetTargetProperty(hby, new PropertyPath("RenderTransform.Children[1].ScaleY"));
                sb.Children.Add(hb);
                sb.Children.Add(hby);
                break;
            }

            case 12: // 💫 별빛 반짝임 — 픽셀이 제각각 랜덤하게 반짝
            {
                var offsets = new[] { 0.0, 0.5, 1.1, 1.6 };
                for (int i = 0; i < 4; i++)
                {
                    double d = offsets[i];
                    var twinkle = new DoubleAnimationUsingKeyFrames();
                    twinkle.KeyFrames.Add(new LinearDoubleKeyFrame(1,    KT(0)));
                    twinkle.KeyFrames.Add(new LinearDoubleKeyFrame(1,    KT(d)));
                    twinkle.KeyFrames.Add(new LinearDoubleKeyFrame(0.05, KT(d + 0.15)));
                    twinkle.KeyFrames.Add(new LinearDoubleKeyFrame(1,    KT(d + 0.35)));
                    twinkle.KeyFrames.Add(new LinearDoubleKeyFrame(0.5,  KT(d + 0.5)));
                    twinkle.KeyFrames.Add(new LinearDoubleKeyFrame(1,    KT(d + 0.65)));
                    twinkle.KeyFrames.Add(new LinearDoubleKeyFrame(1,    KT(3.5)));
                    Storyboard.SetTarget(twinkle, pixels[i]);
                    Storyboard.SetTargetProperty(twinkle, new PropertyPath(UIElement.OpacityProperty));
                    sb.Children.Add(twinkle);
                }
                break;
            }

            case 13: // 💫 나선 등장 — 작게 시작해 회전하며 확대
            {
                var spiralRot = new DoubleAnimation(45 - 180, 45, TimeSpan.FromSeconds(0.9))
                    { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } };
                var spiralSx = new DoubleAnimation(0.4, 1, TimeSpan.FromSeconds(0.9))
                    { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } };
                var spiralSy = new DoubleAnimation(0.4, 1, TimeSpan.FromSeconds(0.9))
                    { EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut } };
                // 등장 후 2.5초 대기, 다시 반복
                var hold = new DoubleAnimation(1, 1, TimeSpan.FromSeconds(2.5))
                { BeginTime = TimeSpan.FromSeconds(0.9) };
                Storyboard.SetTarget(spiralRot, DiamondIcon);
                Storyboard.SetTarget(spiralSx,  DiamondIcon);
                Storyboard.SetTarget(spiralSy,  DiamondIcon);
                Storyboard.SetTarget(hold,       DiamondIcon);
                Storyboard.SetTargetProperty(spiralRot, new PropertyPath("RenderTransform.Children[0].Angle"));
                Storyboard.SetTargetProperty(spiralSx,  new PropertyPath("RenderTransform.Children[1].ScaleX"));
                Storyboard.SetTargetProperty(spiralSy,  new PropertyPath("RenderTransform.Children[1].ScaleY"));
                Storyboard.SetTargetProperty(hold,       new PropertyPath("RenderTransform.Children[1].ScaleX"));
                sb.Children.Add(spiralRot);
                sb.Children.Add(spiralSx);
                sb.Children.Add(spiralSy);
                break;
            }

            case 14: // 💫 색상별 소멸·복원 — 픽셀이 하나씩 사라졌다 다시 나타남
            {
                for (int i = 0; i < 4; i++)
                {
                    double d = i * 0.6;
                    var vanish = new DoubleAnimationUsingKeyFrames();
                    vanish.KeyFrames.Add(new LinearDoubleKeyFrame(1,   KT(0)));
                    vanish.KeyFrames.Add(new LinearDoubleKeyFrame(1,   KT(d)));
                    vanish.KeyFrames.Add(new EasingDoubleKeyFrame(0,   KT(d + 0.3),
                        new QuadraticEase { EasingMode = EasingMode.EaseIn }));
                    vanish.KeyFrames.Add(new EasingDoubleKeyFrame(1,   KT(d + 0.6),
                        new QuadraticEase { EasingMode = EasingMode.EaseOut }));
                    vanish.KeyFrames.Add(new LinearDoubleKeyFrame(1,   KT(3.5)));
                    Storyboard.SetTarget(vanish, pixels[i]);
                    Storyboard.SetTargetProperty(vanish, new PropertyPath(UIElement.OpacityProperty));
                    sb.Children.Add(vanish);
                }
                break;
            }

            case 15: // 💫 스핀+확대 콤보 — 회전하면서 커졌다 작아짐
            {
                var rot = new DoubleAnimation(45, 405, TimeSpan.FromSeconds(2))
                    { EasingFunction = new BackEase { EasingMode = EasingMode.EaseInOut, Amplitude = 0.3 } };
                var sx = new DoubleAnimationUsingKeyFrames();
                sx.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(0)));
                sx.KeyFrames.Add(new EasingDoubleKeyFrame(1.4, KT(1), new QuadraticEase { EasingMode = EasingMode.EaseOut }));
                sx.KeyFrames.Add(new EasingDoubleKeyFrame(1, KT(2), new QuadraticEase { EasingMode = EasingMode.EaseIn }));
                sx.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(3.5)));
                var sy = sx.Clone();
                Storyboard.SetTarget(rot, DiamondIcon);
                Storyboard.SetTarget(sx, DiamondIcon);
                Storyboard.SetTarget(sy, DiamondIcon);
                Storyboard.SetTargetProperty(rot, new PropertyPath("RenderTransform.Children[0].Angle"));
                Storyboard.SetTargetProperty(sx, new PropertyPath("RenderTransform.Children[1].ScaleX"));
                Storyboard.SetTargetProperty(sy, new PropertyPath("RenderTransform.Children[1].ScaleY"));
                sb.Children.Add(rot);
                sb.Children.Add(sx);
                sb.Children.Add(sy);
                break;
            }

            case 16: // 💫 탄성 점프 — 위에서 떨어지며 바운스 (각 픽셀 시차)
            {
                for (int i = 0; i < 4; i++)
                {
                    double d = i * 0.15;
                    var bounce = new DoubleAnimationUsingKeyFrames();
                    bounce.KeyFrames.Add(new LinearDoubleKeyFrame(0, KT(0)));
                    bounce.KeyFrames.Add(new LinearDoubleKeyFrame(0, KT(d)));
                    bounce.KeyFrames.Add(new EasingDoubleKeyFrame(1, KT(d + 0.5),
                        new BounceEase { Bounces = 3, Bounciness = 2.5 }));
                    bounce.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(3)));
                    Storyboard.SetTarget(bounce, pixels[i]);
                    Storyboard.SetTargetProperty(bounce, new PropertyPath(UIElement.OpacityProperty));
                    sb.Children.Add(bounce);
                }
                break;
            }

            case 17: // 💫 진자 운동 — 좌우로 부드럽게 흔들리며 감쇠
            {
                var pendulum = new DoubleAnimationUsingKeyFrames();
                pendulum.KeyFrames.Add(new LinearDoubleKeyFrame(45, KT(0)));
                pendulum.KeyFrames.Add(new EasingDoubleKeyFrame(60, KT(0.3), new SineEase { EasingMode = EasingMode.EaseOut }));
                pendulum.KeyFrames.Add(new EasingDoubleKeyFrame(30, KT(0.9), new SineEase { EasingMode = EasingMode.EaseInOut }));
                pendulum.KeyFrames.Add(new EasingDoubleKeyFrame(55, KT(1.5), new SineEase { EasingMode = EasingMode.EaseInOut }));
                pendulum.KeyFrames.Add(new EasingDoubleKeyFrame(38, KT(2.1), new SineEase { EasingMode = EasingMode.EaseInOut }));
                pendulum.KeyFrames.Add(new EasingDoubleKeyFrame(45, KT(2.5), new SineEase { EasingMode = EasingMode.EaseIn }));
                pendulum.KeyFrames.Add(new LinearDoubleKeyFrame(45, KT(4)));
                Storyboard.SetTarget(pendulum, DiamondIcon);
                Storyboard.SetTargetProperty(pendulum, new PropertyPath("RenderTransform.Children[0].Angle"));
                sb.Children.Add(pendulum);
                break;
            }

            case 18: // 💫 폭죽 — 4개 픽셀이 동시에 빠르게 깜빡이다 정지
            {
                for (int i = 0; i < 4; i++)
                {
                    var rapid = new DoubleAnimationUsingKeyFrames();
                    double offset = i * 0.08;
                    rapid.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(0)));
                    for (int j = 0; j < 6; j++)
                    {
                        double t = offset + j * 0.12;
                        rapid.KeyFrames.Add(new LinearDoubleKeyFrame(j % 2 == 0 ? 0.1 : 1, KT(t)));
                    }
                    rapid.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(1.2)));
                    rapid.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(3.5)));
                    Storyboard.SetTarget(rapid, pixels[i]);
                    Storyboard.SetTargetProperty(rapid, new PropertyPath(UIElement.OpacityProperty));
                    sb.Children.Add(rapid);
                }
                // 동시에 빠르게 확대→축소
                var pop = new DoubleAnimationUsingKeyFrames();
                pop.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(0)));
                pop.KeyFrames.Add(new EasingDoubleKeyFrame(1.5, KT(0.15), new QuadraticEase { EasingMode = EasingMode.EaseOut }));
                pop.KeyFrames.Add(new EasingDoubleKeyFrame(0.8, KT(0.4), new ElasticEase { Oscillations = 2, Springiness = 5 }));
                pop.KeyFrames.Add(new EasingDoubleKeyFrame(1, KT(0.7), new QuadraticEase { EasingMode = EasingMode.EaseOut }));
                pop.KeyFrames.Add(new LinearDoubleKeyFrame(1, KT(3.5)));
                var popY = pop.Clone();
                Storyboard.SetTarget(pop, DiamondIcon);
                Storyboard.SetTarget(popY, DiamondIcon);
                Storyboard.SetTargetProperty(pop, new PropertyPath("RenderTransform.Children[1].ScaleX"));
                Storyboard.SetTargetProperty(popY, new PropertyPath("RenderTransform.Children[1].ScaleY"));
                sb.Children.Add(pop);
                sb.Children.Add(popY);
                break;
            }

            case 19: // 💫 DNA 이중나선 — 대각선 쌍이 교대로 밝아지며 회전
            {
                // 대각선 쌍 교차 깜빡 + 느린 회전
                AddGroupFlash(sb, new[] { pixels[0], pixels[3] }, 0, 4);
                AddGroupFlash(sb, new[] { pixels[1], pixels[2] }, 0.8, 4);
                var dnaRot = new DoubleAnimation(45, 225, TimeSpan.FromSeconds(4))
                    { EasingFunction = new SineEase { EasingMode = EasingMode.EaseInOut } };
                Storyboard.SetTarget(dnaRot, DiamondIcon);
                Storyboard.SetTargetProperty(dnaRot, new PropertyPath("RenderTransform.Children[0].Angle"));
                sb.Children.Add(dnaRot);
                break;
            }
        }

        _iconStoryboard = sb;
        sb.Completed += (_, _) =>
        {
            if (_vm.EnableIconAnimation && IsVisible)
                ApplyRandomIconAnimation();
        };
        sb.Begin(this, true);
    }

    /// <summary>아이콘 클릭 시 다른 랜덤 애니메이션으로 전환.</summary>
    private void DiamondIcon_Click(object sender, MouseButtonEventArgs e)
    {
        if (!_vm.EnableIconAnimation) return;
        ApplyRandomIconAnimation();
    }

}
