using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using Microsoft.Web.WebView2.Core;

namespace AxCopilot.Views;

/// <summary>파일 미리보기 별도 창. WebView2 HWND airspace 문제를 근본적으로 회피합니다.</summary>
public partial class PreviewWindow : Window
{
    private static PreviewWindow? _instance;

    private readonly List<string> _tabs = new();
    private string? _activeTab;
    private bool _webViewInitialized;
    private string? _selectedMood;

    private static readonly string WebView2DataFolder =
        Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                     "AxCopilot", "WebView2_Preview");

    private static readonly HashSet<string> PreviewableExtensions = new(StringComparer.OrdinalIgnoreCase)
    {
        ".html", ".htm", ".md", ".csv", ".txt", ".json", ".xml", ".log",
    };

    public PreviewWindow()
    {
        InitializeComponent();
        Loaded += OnLoaded;
        SourceInitialized += OnSourceInitialized;
        KeyDown += (_, e) => { if (e.Key == Key.Escape) Close(); };
        StateChanged += (_, _) =>
        {
            MaxBtnIcon.Text = WindowState == WindowState.Maximized ? "\uE923" : "\uE922";
        };
        Closed += (_, _) => _instance = null;
    }

    // ─── 상하좌우 리사이즈 (WindowStyle=None 대응) ─────────────
    [DllImport("user32.dll")]
    private static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

    private const int WM_NCHITTEST = 0x0084;
    private const int HTLEFT = 10, HTRIGHT = 11, HTTOP = 12, HTTOPLEFT = 13, HTTOPRIGHT = 14;
    private const int HTBOTTOM = 15, HTBOTTOMLEFT = 16, HTBOTTOMRIGHT = 17;

    private void OnSourceInitialized(object? sender, EventArgs e)
    {
        var hwndSource = (HwndSource)PresentationSource.FromVisual(this);
        hwndSource?.AddHook(WndProc);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        if (msg == WM_NCHITTEST)
        {
            var pt = PointFromScreen(new Point(
                (short)(lParam.ToInt32() & 0xFFFF),
                (short)((lParam.ToInt32() >> 16) & 0xFFFF)));
            const double grip = 8; // 리사이즈 가능 영역 (px)
            var w = ActualWidth;
            var h = ActualHeight;

            if (pt.X < grip && pt.Y < grip) { handled = true; return (IntPtr)HTTOPLEFT; }
            if (pt.X > w - grip && pt.Y < grip) { handled = true; return (IntPtr)HTTOPRIGHT; }
            if (pt.X < grip && pt.Y > h - grip) { handled = true; return (IntPtr)HTBOTTOMLEFT; }
            if (pt.X > w - grip && pt.Y > h - grip) { handled = true; return (IntPtr)HTBOTTOMRIGHT; }
            if (pt.X < grip) { handled = true; return (IntPtr)HTLEFT; }
            if (pt.X > w - grip) { handled = true; return (IntPtr)HTRIGHT; }
            if (pt.Y < grip) { handled = true; return (IntPtr)HTTOP; }
            if (pt.Y > h - grip) { handled = true; return (IntPtr)HTBOTTOM; }
        }
        return IntPtr.Zero;
    }

    // ─── 싱글턴 팩토리 ──────────────────────────────────────────

    /// <summary>파일을 미리보기 창에 표시합니다. 이미 열려 있으면 탭을 추가합니다.</summary>
    public static void ShowPreview(string filePath, string? mood = null)
    {
        if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
            return;

        var ext = Path.GetExtension(filePath).ToLowerInvariant();
        if (!PreviewableExtensions.Contains(ext))
            return;

        Application.Current.Dispatcher.Invoke(() =>
        {
            if (_instance == null || !_instance.IsLoaded)
            {
                _instance = new PreviewWindow();
                // 부모 창의 테마 리소스 전달
                var mainWindow = Application.Current.MainWindow;
                if (mainWindow != null)
                {
                    foreach (var dict in mainWindow.Resources.MergedDictionaries)
                        _instance.Resources.MergedDictionaries.Add(dict);
                }
                _instance._selectedMood = mood;
                _instance.Show();
            }

            _instance.AddTab(filePath);
            _instance.Activate();
        });
    }

    /// <summary>이미 열린 파일의 콘텐츠만 새로고침합니다. 활성 탭이 아닌 파일도 탭 목록에 있으면 활성 탭으로 전환 후 새로고침.</summary>
    public static void RefreshIfOpen(string filePath)
    {
        if (_instance == null || !_instance.IsLoaded) return;
        Application.Current.Dispatcher.Invoke(() =>
        {
            // 현재 활성 탭이면 즉시 새로고침
            if (_instance._activeTab != null &&
                string.Equals(_instance._activeTab, filePath, StringComparison.OrdinalIgnoreCase))
            {
                _instance.LoadContent(filePath);
                return;
            }

            // 탭 목록에 있으면 해당 탭으로 전환 후 새로고침
            var existing = _instance._tabs.FirstOrDefault(
                t => string.Equals(t, filePath, StringComparison.OrdinalIgnoreCase));
            if (existing != null)
            {
                _instance._activeTab = existing;
                _instance.LoadContent(existing);
                _instance.RebuildTabs();
            }
        });
    }

    /// <summary>현재 미리보기 창이 열려 있는지 반환합니다.</summary>
    public static bool IsOpen => _instance != null && _instance.IsLoaded;

    // ─── 초기화 ─────────────────────────────────────────────────

    private async void OnLoaded(object sender, RoutedEventArgs e)
    {
        try
        {
            var env = await CoreWebView2Environment.CreateAsync(
                userDataFolder: WebView2DataFolder);
            await PreviewBrowser.EnsureCoreWebView2Async(env);
            _webViewInitialized = true;

            // 대기 중인 콘텐츠 로드
            if (_activeTab != null)
                LoadContent(_activeTab);
        }
        catch (Exception ex)
        {
            Services.LogService.Warn($"PreviewWindow WebView2 초기화 실패: {ex.Message}");
        }
    }

    // ─── 탭 관리 ────────────────────────────────────────────────

    private void AddTab(string filePath)
    {
        if (!_tabs.Contains(filePath, StringComparer.OrdinalIgnoreCase))
            _tabs.Add(filePath);

        _activeTab = filePath;
        RebuildTabs();
        LoadContent(filePath);
    }

    private void CloseTab(string filePath)
    {
        _tabs.RemoveAll(t => string.Equals(t, filePath, StringComparison.OrdinalIgnoreCase));

        if (_tabs.Count == 0)
        {
            Close();
            return;
        }

        if (string.Equals(_activeTab, filePath, StringComparison.OrdinalIgnoreCase))
        {
            _activeTab = _tabs[^1];
            LoadContent(_activeTab);
        }

        RebuildTabs();
    }

    private void RebuildTabs()
    {
        TabPanel.Children.Clear();

        var accentBrush = TryFindResource("AccentColor") as Brush ?? Brushes.CornflowerBlue;
        var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
        var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
        var borderBrush = TryFindResource("BorderColor") as Brush ?? Brushes.Gray;

        foreach (var tabPath in _tabs)
        {
            var fileName = Path.GetFileName(tabPath);
            var isActive = string.Equals(tabPath, _activeTab, StringComparison.OrdinalIgnoreCase);

            var tabBorder = new Border
            {
                Background = Brushes.Transparent,
                BorderBrush = isActive ? accentBrush : Brushes.Transparent,
                BorderThickness = new Thickness(0, 0, 0, isActive ? 2 : 0),
                Padding = new Thickness(10, 6, 6, 6),
                Cursor = Cursors.Hand,
                MaxWidth = _tabs.Count <= 3 ? 220 : (_tabs.Count <= 5 ? 160 : 110),
            };

            var tabContent = new StackPanel { Orientation = Orientation.Horizontal };

            tabContent.Children.Add(new TextBlock
            {
                Text = fileName,
                FontSize = 11.5,
                Foreground = isActive ? primaryText : secondaryText,
                FontWeight = isActive ? FontWeights.SemiBold : FontWeights.Normal,
                VerticalAlignment = VerticalAlignment.Center,
                TextTrimming = TextTrimming.CharacterEllipsis,
                MaxWidth = tabBorder.MaxWidth - 36,
                ToolTip = tabPath,
            });

            // 닫기 버튼
            var closePath = tabPath;
            var closeBtn = new Border
            {
                Background = Brushes.Transparent,
                CornerRadius = new CornerRadius(3),
                Padding = new Thickness(4, 2, 4, 2),
                Margin = new Thickness(6, 0, 0, 0),
                Cursor = Cursors.Hand,
                VerticalAlignment = VerticalAlignment.Center,
                Child = new TextBlock
                {
                    Text = "\uE711",
                    FontFamily = ThemeResourceHelper.SegoeMdl2,
                    FontSize = 8,
                    Foreground = secondaryText,
                    VerticalAlignment = VerticalAlignment.Center,
                },
            };
            closeBtn.MouseEnter += (s, _) =>
            {
                if (s is Border b)
                    b.Background = new SolidColorBrush(Color.FromArgb(0x30, 0xFF, 0x50, 0x50));
            };
            closeBtn.MouseLeave += (s, _) =>
            {
                if (s is Border b) b.Background = Brushes.Transparent;
            };
            closeBtn.MouseLeftButtonUp += (_, me) =>
            {
                me.Handled = true;
                CloseTab(closePath);
            };

            tabContent.Children.Add(closeBtn);
            tabBorder.Child = tabContent;

            // 탭 클릭 → 활성화
            var clickPath = tabPath;
            tabBorder.MouseLeftButtonUp += (_, me) =>
            {
                if (me.Handled) return;
                me.Handled = true;
                _activeTab = clickPath;
                RebuildTabs();
                LoadContent(clickPath);
            };

            // 호버 효과
            tabBorder.MouseEnter += (s, _) =>
            {
                if (s is Border b && !string.Equals(clickPath, _activeTab, StringComparison.OrdinalIgnoreCase))
                    b.Background = new SolidColorBrush(Color.FromArgb(0x18, 0xFF, 0xFF, 0xFF));
            };
            tabBorder.MouseLeave += (s, _) =>
            {
                if (s is Border b) b.Background = Brushes.Transparent;
            };

            TabPanel.Children.Add(tabBorder);

            // 구분선
            if (tabPath != _tabs[^1])
            {
                TabPanel.Children.Add(new Border
                {
                    Width = 1, Height = 14,
                    Background = borderBrush,
                    Margin = new Thickness(2, 0, 2, 0),
                    VerticalAlignment = VerticalAlignment.Center,
                });
            }
        }

        // 타이틀 업데이트
        if (_activeTab != null)
            TitleText.Text = $"미리보기 — {Path.GetFileName(_activeTab)}";
    }

}
