using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Threading;
using AxCopilot.Services;
using AxCopilot.Services.Agent;
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.Wpf;

namespace AxCopilot.Views;

public class PreviewWindow : Window, IComponentConnector
{
	private static PreviewWindow? _instance;

	private readonly List<string> _tabs = new List<string>();

	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 HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".html", ".htm", ".md", ".csv", ".txt", ".json", ".xml", ".log" };

	private const int WM_NCHITTEST = 132;

	private const int HTLEFT = 10;

	private const int HTRIGHT = 11;

	private const int HTTOP = 12;

	private const int HTTOPLEFT = 13;

	private const int HTTOPRIGHT = 14;

	private const int HTBOTTOM = 15;

	private const int HTBOTTOMLEFT = 16;

	private const int HTBOTTOMRIGHT = 17;

	internal TextBlock TitleText;

	internal TextBlock MaxBtnIcon;

	internal StackPanel TabPanel;

	internal WebView2 PreviewBrowser;

	internal ScrollViewer TextScroll;

	internal TextBlock TextContent;

	internal DataGrid DataGridContent;

	internal TextBlock EmptyMessage;

	private bool _contentLoaded;

	public static bool IsOpen => _instance != null && _instance.IsLoaded;

	public PreviewWindow()
	{
		InitializeComponent();
		base.Loaded += OnLoaded;
		base.SourceInitialized += OnSourceInitialized;
		base.KeyDown += delegate(object _, KeyEventArgs e)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Invalid comparison between Unknown and I4
			if ((int)e.Key == 13)
			{
				Close();
			}
		};
		base.StateChanged += delegate
		{
			MaxBtnIcon.Text = ((base.WindowState == WindowState.Maximized) ? "\ue923" : "\ue922");
		};
		base.Closed += delegate
		{
			_instance = null;
		};
	}

	[DllImport("user32.dll")]
	private static extern nint SendMessage(nint hWnd, int msg, nint wParam, nint lParam);

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

	private nint WndProc(nint hwnd, int msg, nint wParam, nint lParam, ref bool handled)
	{
		//IL_0033: Unknown result type (might be due to invalid IL or missing references)
		//IL_0038: Unknown result type (might be due to invalid IL or missing references)
		//IL_003d: Unknown result type (might be due to invalid IL or missing references)
		if (msg == 132)
		{
			Point val = PointFromScreen(new Point((double)(short)(((IntPtr)lParam).ToInt32() & 0xFFFF), (double)(short)((((IntPtr)lParam).ToInt32() >> 16) & 0xFFFF)));
			double actualWidth = base.ActualWidth;
			double actualHeight = base.ActualHeight;
			if (((Point)(ref val)).X < 8.0 && ((Point)(ref val)).Y < 8.0)
			{
				handled = true;
				return 13;
			}
			if (((Point)(ref val)).X > actualWidth - 8.0 && ((Point)(ref val)).Y < 8.0)
			{
				handled = true;
				return 14;
			}
			if (((Point)(ref val)).X < 8.0 && ((Point)(ref val)).Y > actualHeight - 8.0)
			{
				handled = true;
				return 16;
			}
			if (((Point)(ref val)).X > actualWidth - 8.0 && ((Point)(ref val)).Y > actualHeight - 8.0)
			{
				handled = true;
				return 17;
			}
			if (((Point)(ref val)).X < 8.0)
			{
				handled = true;
				return 10;
			}
			if (((Point)(ref val)).X > actualWidth - 8.0)
			{
				handled = true;
				return 11;
			}
			if (((Point)(ref val)).Y < 8.0)
			{
				handled = true;
				return 12;
			}
			if (((Point)(ref val)).Y > actualHeight - 8.0)
			{
				handled = true;
				return 15;
			}
		}
		return IntPtr.Zero;
	}

	public static void ShowPreview(string filePath, string? mood = null)
	{
		if (string.IsNullOrEmpty(filePath) || !File.Exists(filePath))
		{
			return;
		}
		string item = Path.GetExtension(filePath).ToLowerInvariant();
		if (!PreviewableExtensions.Contains(item))
		{
			return;
		}
		((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
		{
			if (_instance == null || !_instance.IsLoaded)
			{
				_instance = new PreviewWindow();
				Window mainWindow = Application.Current.MainWindow;
				if (mainWindow != null)
				{
					foreach (ResourceDictionary mergedDictionary in mainWindow.Resources.MergedDictionaries)
					{
						_instance.Resources.MergedDictionaries.Add(mergedDictionary);
					}
				}
				_instance._selectedMood = mood;
				_instance.Show();
			}
			_instance.AddTab(filePath);
			_instance.Activate();
		});
	}

	public static void RefreshIfOpen(string filePath)
	{
		if (_instance == null || !_instance.IsLoaded)
		{
			return;
		}
		((DispatcherObject)Application.Current).Dispatcher.Invoke((Action)delegate
		{
			if (_instance._activeTab != null && string.Equals(_instance._activeTab, filePath, StringComparison.OrdinalIgnoreCase))
			{
				_instance.LoadContent(filePath);
			}
			else
			{
				string text = _instance._tabs.FirstOrDefault((string t) => string.Equals(t, filePath, StringComparison.OrdinalIgnoreCase));
				if (text != null)
				{
					_instance._activeTab = text;
					_instance.LoadContent(text);
					_instance.RebuildTabs();
				}
			}
		});
	}

	private async void OnLoaded(object sender, RoutedEventArgs e)
	{
		try
		{
			CoreWebView2Environment env = await CoreWebView2Environment.CreateAsync(null, WebView2DataFolder);
			await PreviewBrowser.EnsureCoreWebView2Async(env);
			_webViewInitialized = true;
			if (_activeTab != null)
			{
				LoadContent(_activeTab);
			}
		}
		catch (Exception ex)
		{
			Exception ex2 = ex;
			LogService.Warn("PreviewWindow WebView2 초기화 실패: " + ex2.Message);
		}
	}

	private void AddTab(string filePath)
	{
		if (!_tabs.Contains<string>(filePath, StringComparer.OrdinalIgnoreCase))
		{
			_tabs.Add(filePath);
		}
		_activeTab = filePath;
		RebuildTabs();
		LoadContent(filePath);
	}

	private void CloseTab(string filePath)
	{
		_tabs.RemoveAll((string t) => string.Equals(t, filePath, StringComparison.OrdinalIgnoreCase));
		if (_tabs.Count == 0)
		{
			Close();
			return;
		}
		if (string.Equals(_activeTab, filePath, StringComparison.OrdinalIgnoreCase))
		{
			List<string> tabs = _tabs;
			_activeTab = tabs[tabs.Count - 1];
			LoadContent(_activeTab);
		}
		RebuildTabs();
	}

	private void RebuildTabs()
	{
		TabPanel.Children.Clear();
		Brush brush = (TryFindResource("AccentColor") as Brush) ?? Brushes.CornflowerBlue;
		Brush brush2 = (TryFindResource("SecondaryText") as Brush) ?? Brushes.Gray;
		Brush brush3 = (TryFindResource("PrimaryText") as Brush) ?? Brushes.White;
		Brush background = (TryFindResource("BorderColor") as Brush) ?? Brushes.Gray;
		foreach (string tab in _tabs)
		{
			string fileName = Path.GetFileName(tab);
			bool flag = string.Equals(tab, _activeTab, StringComparison.OrdinalIgnoreCase);
			Border border = new Border
			{
				Background = Brushes.Transparent,
				BorderBrush = (flag ? brush : Brushes.Transparent),
				BorderThickness = new Thickness(0.0, 0.0, 0.0, flag ? 2 : 0),
				Padding = new Thickness(10.0, 6.0, 6.0, 6.0),
				Cursor = Cursors.Hand,
				MaxWidth = ((_tabs.Count <= 3) ? 220 : ((_tabs.Count <= 5) ? 160 : 110))
			};
			StackPanel stackPanel = new StackPanel
			{
				Orientation = Orientation.Horizontal
			};
			stackPanel.Children.Add(new TextBlock
			{
				Text = fileName,
				FontSize = 11.5,
				Foreground = (flag ? brush3 : brush2),
				FontWeight = (flag ? FontWeights.SemiBold : FontWeights.Normal),
				VerticalAlignment = VerticalAlignment.Center,
				TextTrimming = TextTrimming.CharacterEllipsis,
				MaxWidth = border.MaxWidth - 36.0,
				ToolTip = tab
			});
			string closePath = tab;
			Border border2 = new Border
			{
				Background = Brushes.Transparent,
				CornerRadius = new CornerRadius(3.0),
				Padding = new Thickness(4.0, 2.0, 4.0, 2.0),
				Margin = new Thickness(6.0, 0.0, 0.0, 0.0),
				Cursor = Cursors.Hand,
				VerticalAlignment = VerticalAlignment.Center,
				Child = new TextBlock
				{
					Text = "\ue711",
					FontFamily = new FontFamily("Segoe MDL2 Assets"),
					FontSize = 8.0,
					Foreground = brush2,
					VerticalAlignment = VerticalAlignment.Center
				}
			};
			border2.MouseEnter += delegate(object s, MouseEventArgs _)
			{
				if (s is Border border3)
				{
					border3.Background = new SolidColorBrush(Color.FromArgb(48, byte.MaxValue, 80, 80));
				}
			};
			border2.MouseLeave += delegate(object s, MouseEventArgs _)
			{
				if (s is Border border3)
				{
					border3.Background = Brushes.Transparent;
				}
			};
			border2.MouseLeftButtonUp += delegate(object _, MouseButtonEventArgs me)
			{
				me.Handled = true;
				CloseTab(closePath);
			};
			stackPanel.Children.Add(border2);
			border.Child = stackPanel;
			string clickPath = tab;
			border.MouseLeftButtonUp += delegate(object _, MouseButtonEventArgs me)
			{
				if (!me.Handled)
				{
					me.Handled = true;
					_activeTab = clickPath;
					RebuildTabs();
					LoadContent(clickPath);
				}
			};
			border.MouseEnter += delegate(object s, MouseEventArgs _)
			{
				if (s is Border border3 && !string.Equals(clickPath, _activeTab, StringComparison.OrdinalIgnoreCase))
				{
					border3.Background = new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
				}
			};
			border.MouseLeave += delegate(object s, MouseEventArgs _)
			{
				if (s is Border border3)
				{
					border3.Background = Brushes.Transparent;
				}
			};
			TabPanel.Children.Add(border);
			List<string> tabs = _tabs;
			if (tab != tabs[tabs.Count - 1])
			{
				TabPanel.Children.Add(new Border
				{
					Width = 1.0,
					Height = 14.0,
					Background = background,
					Margin = new Thickness(2.0, 0.0, 2.0, 0.0),
					VerticalAlignment = VerticalAlignment.Center
				});
			}
		}
		if (_activeTab != null)
		{
			TitleText.Text = "미리보기 — " + Path.GetFileName(_activeTab);
		}
	}

	private async void LoadContent(string filePath)
	{
		string ext = Path.GetExtension(filePath).ToLowerInvariant();
		PreviewBrowser.Visibility = Visibility.Collapsed;
		TextScroll.Visibility = Visibility.Collapsed;
		DataGridContent.Visibility = Visibility.Collapsed;
		EmptyMessage.Visibility = Visibility.Collapsed;
		if (!File.Exists(filePath))
		{
			EmptyMessage.Text = "파일을 찾을 수 없습니다";
			EmptyMessage.Visibility = Visibility.Visible;
			return;
		}
		try
		{
			switch (ext)
			{
			case ".html":
			case ".htm":
				if (!_webViewInitialized)
				{
					return;
				}
				PreviewBrowser.Source = new Uri(filePath);
				PreviewBrowser.Visibility = Visibility.Visible;
				break;
			case ".csv":
				LoadCsvContent(filePath);
				DataGridContent.Visibility = Visibility.Visible;
				break;
			case ".md":
			{
				if (!_webViewInitialized)
				{
					return;
				}
				string mdText = File.ReadAllText(filePath);
				if (mdText.Length > 50000)
				{
					mdText = mdText.Substring(0, 50000);
				}
				string mdHtml = TemplateService.RenderMarkdownToHtml(mdText, _selectedMood ?? "modern");
				PreviewBrowser.NavigateToString(mdHtml);
				PreviewBrowser.Visibility = Visibility.Visible;
				break;
			}
			case ".txt":
			case ".json":
			case ".xml":
			case ".log":
			{
				string text = File.ReadAllText(filePath);
				if (text.Length > 50000)
				{
					text = text.Substring(0, 50000) + "\n\n... (이후 생략)";
				}
				TextContent.Text = text;
				TextScroll.Visibility = Visibility.Visible;
				break;
			}
			default:
				EmptyMessage.Text = "미리보기할 수 없는 파일 형식입니다";
				EmptyMessage.Visibility = Visibility.Visible;
				break;
			}
		}
		catch (Exception ex)
		{
			Exception ex2 = ex;
			TextContent.Text = "미리보기 오류: " + ex2.Message;
			TextScroll.Visibility = Visibility.Visible;
		}
		await Task.CompletedTask;
	}

	private void LoadCsvContent(string filePath)
	{
		string[] array = File.ReadAllLines(filePath);
		if (array.Length == 0)
		{
			return;
		}
		DataTable dataTable = new DataTable();
		string[] array2 = ParseCsvLine(array[0]);
		string[] array3 = array2;
		foreach (string columnName in array3)
		{
			dataTable.Columns.Add(columnName);
		}
		int num = Math.Min(array.Length, 501);
		for (int j = 1; j < num; j++)
		{
			string[] array4 = ParseCsvLine(array[j]);
			DataRow dataRow = dataTable.NewRow();
			for (int k = 0; k < Math.Min(array4.Length, array2.Length); k++)
			{
				dataRow[k] = array4[k];
			}
			dataTable.Rows.Add(dataRow);
		}
		DataGridContent.ItemsSource = dataTable.DefaultView;
	}

	private static string[] ParseCsvLine(string line)
	{
		List<string> list = new List<string>();
		StringBuilder stringBuilder = new StringBuilder();
		bool flag = false;
		for (int i = 0; i < line.Length; i++)
		{
			char c = line[i];
			if (flag)
			{
				if (c == '"' && i + 1 < line.Length && line[i + 1] == '"')
				{
					stringBuilder.Append('"');
					i++;
				}
				else if (c == '"')
				{
					flag = false;
				}
				else
				{
					stringBuilder.Append(c);
				}
				continue;
			}
			switch (c)
			{
			case '"':
				flag = true;
				break;
			case ',':
				list.Add(stringBuilder.ToString());
				stringBuilder.Clear();
				break;
			default:
				stringBuilder.Append(c);
				break;
			}
		}
		list.Add(stringBuilder.ToString());
		return list.ToArray();
	}

	private void TitleBar_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
	{
		if (e.ClickCount == 2)
		{
			ToggleMaximize();
		}
		else
		{
			DragMove();
		}
	}

	private void OpenExternalBtn_Click(object sender, MouseButtonEventArgs e)
	{
		e.Handled = true;
		if (_activeTab == null || !File.Exists(_activeTab))
		{
			return;
		}
		try
		{
			Process.Start(new ProcessStartInfo
			{
				FileName = _activeTab,
				UseShellExecute = true
			});
		}
		catch (Exception ex)
		{
			LogService.Warn("외부 프로그램 열기 실패: " + ex.Message);
		}
	}

	private void MinBtn_Click(object sender, MouseButtonEventArgs e)
	{
		e.Handled = true;
		base.WindowState = WindowState.Minimized;
	}

	private void MaxBtn_Click(object sender, MouseButtonEventArgs e)
	{
		e.Handled = true;
		ToggleMaximize();
	}

	private void CloseBtn_Click(object sender, MouseButtonEventArgs e)
	{
		e.Handled = true;
		Close();
	}

	private void ToggleMaximize()
	{
		base.WindowState = ((base.WindowState != WindowState.Maximized) ? WindowState.Maximized : WindowState.Normal);
	}

	private void TitleBtn_Enter(object sender, MouseEventArgs e)
	{
		if (sender is Border border)
		{
			border.Background = (TryFindResource("ItemHoverBackground") as Brush) ?? new SolidColorBrush(Color.FromArgb(24, byte.MaxValue, byte.MaxValue, byte.MaxValue));
		}
	}

	private void CloseBtnEnter(object sender, MouseEventArgs e)
	{
		if (sender is Border border)
		{
			border.Background = new SolidColorBrush(Color.FromArgb(68, byte.MaxValue, 64, 64));
		}
	}

	private void TitleBtn_Leave(object sender, MouseEventArgs e)
	{
		if (sender is Border border)
		{
			border.Background = Brushes.Transparent;
		}
	}

	[DebuggerNonUserCode]
	[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
	public void InitializeComponent()
	{
		if (!_contentLoaded)
		{
			_contentLoaded = true;
			Uri resourceLocator = new Uri("/AxCopilot;component/views/previewwindow.xaml", UriKind.Relative);
			Application.LoadComponent(this, resourceLocator);
		}
	}

	[DebuggerNonUserCode]
	[GeneratedCode("PresentationBuildTasks", "10.0.5.0")]
	[EditorBrowsable(EditorBrowsableState.Never)]
	void IComponentConnector.Connect(int connectionId, object target)
	{
		switch (connectionId)
		{
		case 1:
			((Border)target).MouseLeftButtonDown += TitleBar_MouseLeftButtonDown;
			break;
		case 2:
			TitleText = (TextBlock)target;
			break;
		case 3:
			((Border)target).MouseLeftButtonDown += OpenExternalBtn_Click;
			((Border)target).MouseEnter += TitleBtn_Enter;
			((Border)target).MouseLeave += TitleBtn_Leave;
			break;
		case 4:
			((Border)target).MouseLeftButtonDown += MinBtn_Click;
			((Border)target).MouseEnter += TitleBtn_Enter;
			((Border)target).MouseLeave += TitleBtn_Leave;
			break;
		case 5:
			((Border)target).MouseLeftButtonDown += MaxBtn_Click;
			((Border)target).MouseEnter += TitleBtn_Enter;
			((Border)target).MouseLeave += TitleBtn_Leave;
			break;
		case 6:
			MaxBtnIcon = (TextBlock)target;
			break;
		case 7:
			((Border)target).MouseLeftButtonDown += CloseBtn_Click;
			((Border)target).MouseEnter += CloseBtnEnter;
			((Border)target).MouseLeave += TitleBtn_Leave;
			break;
		case 8:
			TabPanel = (StackPanel)target;
			break;
		case 9:
			PreviewBrowser = (WebView2)target;
			break;
		case 10:
			TextScroll = (ScrollViewer)target;
			break;
		case 11:
			TextContent = (TextBlock)target;
			break;
		case 12:
			DataGridContent = (DataGrid)target;
			break;
		case 13:
			EmptyMessage = (TextBlock)target;
			break;
		default:
			_contentLoaded = true;
			break;
		}
	}
}
