using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows.Media;
using AxCopilot.Models;
using AxCopilot.Services;

namespace AxCopilot.ViewModels;

public class StatisticsViewModel : INotifyPropertyChanged
{
	private class FavFileEntry
	{
		[JsonPropertyName("name")]
		public string Name { get; set; } = "";

		[JsonPropertyName("path")]
		public string Path { get; set; } = "";
	}

	private const double MaxBarHeight = 66.0;

	private const double MaxBarWidth = 200.0;

	private bool _hasFavorites;

	private string _todayDate = "";

	private string _todaySummary = "";

	private string _peakDate = "";

	private string _peakDaySummary = "";

	private string _weekSummary = "";

	private string _totalOpensSummary = "";

	private string _agentSummary = "";

	private double _promptBarWidth;

	private double _completionBarWidth;

	private string _promptTokenLabel = "";

	private string _completionTokenLabel = "";

	private string _tokenRatioSummary = "";

	public ObservableCollection<DayBarItem> LauncherOpenBars { get; } = new ObservableCollection<DayBarItem>();

	public ObservableCollection<DayBarItem> ActiveTimeBars { get; } = new ObservableCollection<DayBarItem>();

	public ObservableCollection<CommandStatItem> TopCommands { get; } = new ObservableCollection<CommandStatItem>();

	public ObservableCollection<FavoriteStatItem> TopFavorites { get; } = new ObservableCollection<FavoriteStatItem>();

	public ObservableCollection<DayBarItem> ChatCountBars { get; } = new ObservableCollection<DayBarItem>();

	public ObservableCollection<DayBarItem> TokenUsageBars { get; } = new ObservableCollection<DayBarItem>();

	public ObservableCollection<DayBarItem> WeekdayAvgBars { get; } = new ObservableCollection<DayBarItem>();

	public ObservableCollection<TabRatioItem> TabChatRatios { get; } = new ObservableCollection<TabRatioItem>();

	public bool HasFavorites
	{
		get
		{
			return _hasFavorites;
		}
		private set
		{
			_hasFavorites = value;
			OnPropertyChanged("HasFavorites");
		}
	}

	public string TodayDate
	{
		get
		{
			return _todayDate;
		}
		set
		{
			_todayDate = value;
			OnPropertyChanged("TodayDate");
		}
	}

	public string TodaySummary
	{
		get
		{
			return _todaySummary;
		}
		set
		{
			_todaySummary = value;
			OnPropertyChanged("TodaySummary");
		}
	}

	public string PeakDate
	{
		get
		{
			return _peakDate;
		}
		set
		{
			_peakDate = value;
			OnPropertyChanged("PeakDate");
		}
	}

	public string PeakDaySummary
	{
		get
		{
			return _peakDaySummary;
		}
		set
		{
			_peakDaySummary = value;
			OnPropertyChanged("PeakDaySummary");
		}
	}

	public string WeekSummary
	{
		get
		{
			return _weekSummary;
		}
		set
		{
			_weekSummary = value;
			OnPropertyChanged("WeekSummary");
		}
	}

	public string TotalOpensSummary
	{
		get
		{
			return _totalOpensSummary;
		}
		set
		{
			_totalOpensSummary = value;
			OnPropertyChanged("TotalOpensSummary");
		}
	}

	public string AgentSummary
	{
		get
		{
			return _agentSummary;
		}
		set
		{
			_agentSummary = value;
			OnPropertyChanged("AgentSummary");
		}
	}

	public double PromptBarWidth
	{
		get
		{
			return _promptBarWidth;
		}
		set
		{
			_promptBarWidth = value;
			OnPropertyChanged("PromptBarWidth");
		}
	}

	public double CompletionBarWidth
	{
		get
		{
			return _completionBarWidth;
		}
		set
		{
			_completionBarWidth = value;
			OnPropertyChanged("CompletionBarWidth");
		}
	}

	public string PromptTokenLabel
	{
		get
		{
			return _promptTokenLabel;
		}
		set
		{
			_promptTokenLabel = value;
			OnPropertyChanged("PromptTokenLabel");
		}
	}

	public string CompletionTokenLabel
	{
		get
		{
			return _completionTokenLabel;
		}
		set
		{
			_completionTokenLabel = value;
			OnPropertyChanged("CompletionTokenLabel");
		}
	}

	public string TokenRatioSummary
	{
		get
		{
			return _tokenRatioSummary;
		}
		set
		{
			_tokenRatioSummary = value;
			OnPropertyChanged("TokenRatioSummary");
		}
	}

	public event PropertyChangedEventHandler? PropertyChanged;

	public StatisticsViewModel()
	{
		Refresh();
	}

	public void Refresh()
	{
		List<DailyUsageStats> stats = UsageStatisticsService.GetStats();
		string today = DateTime.Today.ToString("yyyy-MM-dd");
		BuildLauncherOpenChart(stats, today);
		BuildActiveTimeChart(stats, today);
		BuildChatCountChart(stats, today);
		BuildTokenUsageChart(stats, today);
		BuildTopCommands(stats);
		BuildWeekdayAvgChart(stats);
		BuildTabChatRatios(stats);
		BuildTokenRatio(stats);
		BuildSummaryCards(stats, today);
		BuildTopFavorites();
	}

	private void BuildLauncherOpenChart(List<DailyUsageStats> stats, string today)
	{
		List<DailyUsageStats> list = stats.TakeLast(14).ToList();
		int num = list.Max((DailyUsageStats s) => s.LauncherOpens);
		if (num == 0)
		{
			num = 1;
		}
		LauncherOpenBars.Clear();
		foreach (DailyUsageStats item in list)
		{
			DateTime result;
			DateTime dateTime = (DateTime.TryParse(item.Date, out result) ? result : DateTime.MinValue);
			LauncherOpenBars.Add(new DayBarItem
			{
				DateLabel = ((dateTime != DateTime.MinValue) ? $"{dateTime.Month}/{dateTime.Day}" : ""),
				DayLabel = ((dateTime != DateTime.MinValue) ? GetKoreanDayOfWeek(dateTime.DayOfWeek) : ""),
				Value = item.LauncherOpens,
				BarHeight = 66.0 * (double)item.LauncherOpens / (double)num,
				ValueLabel = ((item.LauncherOpens > 0) ? item.LauncherOpens.ToString() : ""),
				ToolTipText = ((dateTime != DateTime.MinValue) ? $"{dateTime:yyyy-MM-dd} ({GetKoreanDayOfWeek(dateTime.DayOfWeek)})\n호출 {item.LauncherOpens}회" : ""),
				IsToday = (item.Date == today)
			});
		}
	}

	private void BuildActiveTimeChart(List<DailyUsageStats> stats, string today)
	{
		List<DailyUsageStats> list = stats.TakeLast(14).ToList();
		int num = list.Max((DailyUsageStats s) => s.ActiveSeconds);
		if (num == 0)
		{
			num = 1;
		}
		ActiveTimeBars.Clear();
		foreach (DailyUsageStats item in list)
		{
			DateTime result;
			DateTime dateTime = (DateTime.TryParse(item.Date, out result) ? result : DateTime.MinValue);
			ActiveTimeBars.Add(new DayBarItem
			{
				DateLabel = ((dateTime != DateTime.MinValue) ? $"{dateTime.Month}/{dateTime.Day}" : ""),
				DayLabel = ((dateTime != DateTime.MinValue) ? GetKoreanDayOfWeek(dateTime.DayOfWeek) : ""),
				Value = item.ActiveSeconds,
				BarHeight = 66.0 * (double)item.ActiveSeconds / (double)num,
				ValueLabel = FormatActiveTime(item.ActiveSeconds),
				ToolTipText = ((dateTime != DateTime.MinValue) ? $"{dateTime:yyyy-MM-dd} ({GetKoreanDayOfWeek(dateTime.DayOfWeek)})\n활성 {FormatActiveTime(item.ActiveSeconds)}" : ""),
				IsToday = (item.Date == today)
			});
		}
	}

	private void BuildChatCountChart(List<DailyUsageStats> stats, string today)
	{
		List<DailyUsageStats> list = stats.TakeLast(14).ToList();
		int num = list.Max(delegate(DailyUsageStats s)
		{
			int num3 = 0;
			foreach (KeyValuePair<string, int> chatCount in s.ChatCounts)
			{
				num3 += chatCount.Value;
			}
			return num3;
		});
		if (num == 0)
		{
			num = 1;
		}
		ChatCountBars.Clear();
		foreach (DailyUsageStats item in list)
		{
			DateTime result;
			DateTime value = (DateTime.TryParse(item.Date, out result) ? result : DateTime.MinValue);
			int valueOrDefault = item.ChatCounts.GetValueOrDefault("Chat");
			int valueOrDefault2 = item.ChatCounts.GetValueOrDefault("Cowork");
			int valueOrDefault3 = item.ChatCounts.GetValueOrDefault("Code");
			int num2 = valueOrDefault + valueOrDefault2 + valueOrDefault3;
			bool isToday = item.Date == today;
			ChatCountBars.Add(new DayBarItem
			{
				DateLabel = value.ToString("M/d"),
				DayLabel = value.ToString("ddd").Substring(0, 1),
				Value = num2,
				BarHeight = ((num2 > 0) ? ((double)num2 * 66.0 / (double)num) : 2.0),
				ValueLabel = ((num2 > 0) ? num2.ToString() : ""),
				ToolTipText = $"{item.Date} ({value:ddd})\nChat: {valueOrDefault}회 · Cowork: {valueOrDefault2}회 · Code: {valueOrDefault3}회",
				IsToday = isToday
			});
		}
	}

	private void BuildTokenUsageChart(List<DailyUsageStats> stats, string today)
	{
		List<DailyUsageStats> list = stats.TakeLast(14).ToList();
		long num = list.Max((DailyUsageStats s) => s.TotalTokens);
		if (num == 0)
		{
			num = 1L;
		}
		TokenUsageBars.Clear();
		foreach (DailyUsageStats item in list)
		{
			DateTime result;
			DateTime value = (DateTime.TryParse(item.Date, out result) ? result : DateTime.MinValue);
			bool isToday = item.Date == today;
			long totalTokens = item.TotalTokens;
			TokenUsageBars.Add(new DayBarItem
			{
				DateLabel = value.ToString("M/d"),
				DayLabel = value.ToString("ddd").Substring(0, 1),
				Value = (int)Math.Min(totalTokens, 2147483647L),
				BarHeight = ((totalTokens > 0) ? ((double)totalTokens * 66.0 / (double)num) : 2.0),
				ValueLabel = ((totalTokens > 0) ? FormatTokens(totalTokens) : ""),
				ToolTipText = $"{item.Date} ({value:ddd})\n프롬프트: {item.PromptTokens:N0} · 완료: {item.CompletionTokens:N0} · 합계: {item.TotalTokens:N0}",
				IsToday = isToday
			});
		}
	}

	private static string FormatTokens(long tokens)
	{
		if (1 == 0)
		{
		}
		string result = ((tokens >= 1000000) ? $"{(double)tokens / 1000000.0:F1}M" : ((tokens < 1000) ? tokens.ToString() : $"{(double)tokens / 1000.0:F1}K"));
		if (1 == 0)
		{
		}
		return result;
	}

	private void BuildWeekdayAvgChart(List<DailyUsageStats> stats)
	{
		Dictionary<DayOfWeek, List<int>> groups = new Dictionary<DayOfWeek, List<int>>();
		DayOfWeek[] values = Enum.GetValues<DayOfWeek>();
		foreach (DayOfWeek key in values)
		{
			groups[key] = new List<int>();
		}
		foreach (DailyUsageStats stat in stats)
		{
			if (DateTime.TryParse(stat.Date, out var result))
			{
				groups[result.DayOfWeek].Add(stat.LauncherOpens);
			}
		}
		DayOfWeek[] array = new DayOfWeek[7]
		{
			DayOfWeek.Monday,
			DayOfWeek.Tuesday,
			DayOfWeek.Wednesday,
			DayOfWeek.Thursday,
			DayOfWeek.Friday,
			DayOfWeek.Saturday,
			DayOfWeek.Sunday
		};
		double num = array.Max((DayOfWeek dow) => (groups[dow].Count > 0) ? groups[dow].Average() : 0.0);
		if (num < 1.0)
		{
			num = 1.0;
		}
		WeekdayAvgBars.Clear();
		DayOfWeek[] array2 = array;
		foreach (DayOfWeek dayOfWeek in array2)
		{
			List<int> list = groups[dayOfWeek];
			double num3 = ((list.Count > 0) ? list.Average() : 0.0);
			WeekdayAvgBars.Add(new DayBarItem
			{
				DateLabel = "",
				DayLabel = GetKoreanDayOfWeek(dayOfWeek),
				Value = (int)Math.Round(num3),
				BarHeight = ((num3 > 0.0) ? (num3 * 66.0 / num) : 2.0),
				ValueLabel = ((num3 > 0.0) ? num3.ToString("F1") : ""),
				ToolTipText = $"{GetKoreanDayOfWeek(dayOfWeek)}요일 평균 {num3:F1}회 ({list.Count}일 데이터)",
				IsToday = (DateTime.Today.DayOfWeek == dayOfWeek)
			});
		}
	}

	private void BuildTabChatRatios(List<DailyUsageStats> stats)
	{
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		foreach (DailyUsageStats stat in stats)
		{
			num += stat.ChatCounts.GetValueOrDefault("Chat");
			num2 += stat.ChatCounts.GetValueOrDefault("Cowork");
			num3 += stat.ChatCounts.GetValueOrDefault("Code");
		}
		int num4 = num + num2 + num3;
		if (num4 == 0)
		{
			num4 = 1;
		}
		TabChatRatios.Clear();
		TabChatRatios.Add(new TabRatioItem
		{
			TabName = "Chat",
			Count = num,
			Percentage = 100.0 * (double)num / (double)num4,
			BarWidth = 300.0 * (double)num / (double)num4,
			PercentLabel = $"{100.0 * (double)num / (double)num4:F0}%  ({num}회)",
			Color = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#818CF8"))
		});
		TabChatRatios.Add(new TabRatioItem
		{
			TabName = "Cowork",
			Count = num2,
			Percentage = 100.0 * (double)num2 / (double)num4,
			BarWidth = 300.0 * (double)num2 / (double)num4,
			PercentLabel = $"{100.0 * (double)num2 / (double)num4:F0}%  ({num2}회)",
			Color = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#10B981"))
		});
		TabChatRatios.Add(new TabRatioItem
		{
			TabName = "Code",
			Count = num3,
			Percentage = 100.0 * (double)num3 / (double)num4,
			BarWidth = 300.0 * (double)num3 / (double)num4,
			PercentLabel = $"{100.0 * (double)num3 / (double)num4:F0}%  ({num3}회)",
			Color = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#F59E0B"))
		});
	}

	private void BuildTokenRatio(List<DailyUsageStats> stats)
	{
		long num = stats.Sum((DailyUsageStats s) => s.PromptTokens);
		long num2 = stats.Sum((DailyUsageStats s) => s.CompletionTokens);
		long num3 = num + num2;
		if (num3 == 0)
		{
			num3 = 1L;
		}
		PromptBarWidth = 400.0 * (double)num / (double)num3;
		CompletionBarWidth = 400.0 * (double)num2 / (double)num3;
		PromptTokenLabel = $"입력 {FormatTokens(num)} ({100.0 * (double)num / (double)num3:F0}%)";
		CompletionTokenLabel = $"출력 {FormatTokens(num2)} ({100.0 * (double)num2 / (double)num3:F0}%)";
		TokenRatioSummary = $"30일 합계  입력 {FormatTokens(num)} + 출력 {FormatTokens(num2)} = {FormatTokens(num + num2)}";
	}

	private void BuildTopCommands(List<DailyUsageStats> stats)
	{
		Dictionary<string, int> dictionary = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
		foreach (DailyUsageStats stat in stats)
		{
			foreach (var (key, num2) in stat.CommandUsage)
			{
				dictionary.TryGetValue(key, out var value);
				dictionary[key] = value + num2;
			}
		}
		List<KeyValuePair<string, int>> list = dictionary.OrderByDescending((KeyValuePair<string, int> kv) => kv.Value).Take(10).ToList();
		int num3 = ((list.Count <= 0) ? 1 : list[0].Value);
		TopCommands.Clear();
		for (int num4 = 0; num4 < list.Count; num4++)
		{
			TopCommands.Add(new CommandStatItem
			{
				Rank = num4 + 1,
				Command = list[num4].Key,
				Count = list[num4].Value,
				BarWidth = 200.0 * (double)list[num4].Value / (double)num3
			});
		}
	}

	private void BuildSummaryCards(List<DailyUsageStats> stats, string today)
	{
		TodayDate = DateTime.Today.ToString("yyyy년 M월 d일");
		DailyUsageStats dailyUsageStats = stats.FirstOrDefault((DailyUsageStats s) => s.Date == today);
		TodaySummary = ((dailyUsageStats != null) ? $"{dailyUsageStats.LauncherOpens}회 호출  ·  {FormatActiveTime(dailyUsageStats.ActiveSeconds)}" : "데이터 없음");
		DailyUsageStats dailyUsageStats2 = stats.OrderByDescending((DailyUsageStats s) => s.LauncherOpens).FirstOrDefault();
		if (dailyUsageStats2 != null && dailyUsageStats2.LauncherOpens > 0)
		{
			PeakDate = (DateTime.TryParse(dailyUsageStats2.Date, out var result) ? result.ToString("yyyy년 M월 d일") : dailyUsageStats2.Date);
			PeakDaySummary = $"{dailyUsageStats2.LauncherOpens}회 호출";
		}
		else
		{
			PeakDate = "";
			PeakDaySummary = "기록 없음";
		}
		DateTime weekStart = DateTime.Today.AddDays(0 - DateTime.Today.DayOfWeek);
		DateTime result2;
		int value = stats.Where((DailyUsageStats s) => DateTime.TryParse(s.Date, out result2) && result2 >= weekStart).Sum((DailyUsageStats s) => s.LauncherOpens);
		WeekSummary = $"이번 주  {value}회";
		int value2 = stats.Sum((DailyUsageStats s) => s.LauncherOpens);
		TotalOpensSummary = $"30일 합계  {value2}회";
		int value3 = stats.Sum((DailyUsageStats s) => s.ChatCounts.Values.Sum());
		long tokens = stats.Sum((DailyUsageStats s) => s.TotalTokens);
		int value4 = dailyUsageStats?.ChatCounts.Values.Sum() ?? 0;
		long tokens2 = dailyUsageStats?.TotalTokens ?? 0;
		AgentSummary = $"오늘 {value4}회 대화 · {FormatTokens(tokens2)} 토큰  |  30일 합계 {value3}회 · {FormatTokens(tokens)} 토큰";
	}

	private void BuildTopFavorites()
	{
		TopFavorites.Clear();
		string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "favorites.json");
		if (!File.Exists(path))
		{
			HasFavorites = false;
			return;
		}
		try
		{
			JsonSerializerOptions options = new JsonSerializerOptions
			{
				PropertyNameCaseInsensitive = true
			};
			List<FavFileEntry> source = JsonSerializer.Deserialize<List<FavFileEntry>>(File.ReadAllText(path), options) ?? new List<FavFileEntry>();
			List<FavFileEntry> list = source.Take(6).ToList();
			if (list.Count == 0)
			{
				HasFavorites = false;
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				FavFileEntry favFileEntry = list[i];
				string path2 = Environment.ExpandEnvironmentVariables(favFileEntry.Path);
				bool flag = Directory.Exists(path2);
				bool exists = flag || File.Exists(path2);
				TopFavorites.Add(new FavoriteStatItem
				{
					Rank = i + 1,
					Name = favFileEntry.Name,
					Path = favFileEntry.Path,
					Icon = (flag ? "\ue8b7" : "\ue8a5"),
					Exists = exists
				});
			}
			HasFavorites = TopFavorites.Count > 0;
		}
		catch
		{
			HasFavorites = false;
		}
	}

	private static string GetKoreanDayOfWeek(DayOfWeek dow)
	{
		if (1 == 0)
		{
		}
		string result = dow switch
		{
			DayOfWeek.Monday => "월", 
			DayOfWeek.Tuesday => "화", 
			DayOfWeek.Wednesday => "수", 
			DayOfWeek.Thursday => "목", 
			DayOfWeek.Friday => "금", 
			DayOfWeek.Saturday => "토", 
			_ => "일", 
		};
		if (1 == 0)
		{
		}
		return result;
	}

	private static string FormatActiveTime(int totalSeconds)
	{
		if (totalSeconds <= 0)
		{
			return "";
		}
		int num = totalSeconds / 3600;
		int num2 = totalSeconds % 3600 / 60;
		if (num > 0 && num2 > 0)
		{
			return $"{num}시간 {num2}분";
		}
		if (num <= 0)
		{
			if (num2 <= 0)
			{
				return $"{totalSeconds}초";
			}
			return $"{num2}분";
		}
		return $"{num}시간";
	}

	protected void OnPropertyChanged([CallerMemberName] string? n = null)
	{
		this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(n));
	}
}
