using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;

namespace AxCopilot.Services;

public static class AgentStatsService
{
	public record AgentSessionRecord
	{
		[JsonPropertyName("ts")]
		public DateTime Timestamp { get; init; } = DateTime.Now;

		[JsonPropertyName("tab")]
		public string Tab { get; init; } = "";

		[JsonPropertyName("model")]
		public string Model { get; init; } = "";

		[JsonPropertyName("calls")]
		public int ToolCalls { get; init; }

		[JsonPropertyName("ok")]
		public int SuccessCount { get; init; }

		[JsonPropertyName("fail")]
		public int FailCount { get; init; }

		[JsonPropertyName("itok")]
		public int InputTokens { get; init; }

		[JsonPropertyName("otok")]
		public int OutputTokens { get; init; }

		[JsonPropertyName("ms")]
		public long DurationMs { get; init; }

		[JsonPropertyName("tools")]
		public List<string> UsedTools { get; init; } = new List<string>();
	}

	public record AgentStatsSummary
	{
		public int TotalSessions { get; init; }

		public int TotalToolCalls { get; init; }

		public int TotalTokens { get; init; }

		public int TotalInputTokens { get; init; }

		public int TotalOutputTokens { get; init; }

		public long TotalDurationMs { get; init; }

		public Dictionary<string, int> ToolFrequency { get; init; } = new Dictionary<string, int>();

		public Dictionary<string, int> ModelBreakdown { get; init; } = new Dictionary<string, int>();

		public Dictionary<string, int> TabBreakdown { get; init; } = new Dictionary<string, int>();

		public Dictionary<string, int> DailySessions { get; init; } = new Dictionary<string, int>();

		public Dictionary<string, int> DailyTokens { get; init; } = new Dictionary<string, int>();
	}

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

	private static readonly string StatsFile = Path.Combine(StatsDir, "agent_stats.json");

	private static readonly JsonSerializerOptions _jsonOpts = new JsonSerializerOptions
	{
		WriteIndented = false,
		PropertyNamingPolicy = JsonNamingPolicy.CamelCase
	};

	public static void RecordSession(AgentSessionRecord record)
	{
		Task.Run(delegate
		{
			try
			{
				if (!Directory.Exists(StatsDir))
				{
					Directory.CreateDirectory(StatsDir);
				}
				string text = JsonSerializer.Serialize(record, _jsonOpts);
				File.AppendAllText(StatsFile, text + "\n");
			}
			catch (Exception ex)
			{
				LogService.Warn("통계 기록 실패: " + ex.Message);
			}
		});
	}

	public static AgentStatsSummary Aggregate(int days = 0)
	{
		List<AgentSessionRecord> records = LoadRecords(days);
		return BuildSummary(records);
	}

	public static List<AgentSessionRecord> LoadRecords(int days = 0)
	{
		if (!File.Exists(StatsFile))
		{
			return new List<AgentSessionRecord>();
		}
		DateTime dateTime = ((days > 0) ? DateTime.Now.AddDays(-days) : DateTime.MinValue);
		List<AgentSessionRecord> list = new List<AgentSessionRecord>();
		foreach (string item in File.ReadLines(StatsFile))
		{
			if (string.IsNullOrWhiteSpace(item))
			{
				continue;
			}
			try
			{
				AgentSessionRecord agentSessionRecord = JsonSerializer.Deserialize<AgentSessionRecord>(item, _jsonOpts);
				if (agentSessionRecord != null && agentSessionRecord.Timestamp >= dateTime)
				{
					list.Add(agentSessionRecord);
				}
			}
			catch
			{
			}
		}
		return list;
	}

	private static AgentStatsSummary BuildSummary(List<AgentSessionRecord> records)
	{
		Dictionary<string, int> dictionary = new Dictionary<string, int>();
		Dictionary<string, int> dictionary2 = new Dictionary<string, int>();
		Dictionary<string, int> dictionary3 = new Dictionary<string, int>();
		Dictionary<string, int> dictionary4 = new Dictionary<string, int>();
		Dictionary<string, int> dictionary5 = new Dictionary<string, int>();
		int num = 0;
		int num2 = 0;
		int num3 = 0;
		long num4 = 0L;
		foreach (AgentSessionRecord record in records)
		{
			num += record.ToolCalls;
			num2 += record.InputTokens;
			num3 += record.OutputTokens;
			num4 += record.DurationMs;
			foreach (string usedTool in record.UsedTools)
			{
				dictionary[usedTool] = dictionary.GetValueOrDefault(usedTool) + 1;
			}
			if (!string.IsNullOrEmpty(record.Model))
			{
				dictionary2[record.Model] = dictionary2.GetValueOrDefault(record.Model) + 1;
			}
			if (!string.IsNullOrEmpty(record.Tab))
			{
				dictionary3[record.Tab] = dictionary3.GetValueOrDefault(record.Tab) + 1;
			}
			string key = record.Timestamp.ToString("yyyy-MM-dd");
			dictionary4[key] = dictionary4.GetValueOrDefault(key) + 1;
			dictionary5[key] = dictionary5.GetValueOrDefault(key) + record.InputTokens + record.OutputTokens;
		}
		return new AgentStatsSummary
		{
			TotalSessions = records.Count,
			TotalToolCalls = num,
			TotalTokens = num2 + num3,
			TotalInputTokens = num2,
			TotalOutputTokens = num3,
			TotalDurationMs = num4,
			ToolFrequency = dictionary.OrderByDescending((KeyValuePair<string, int> kv) => kv.Value).Take(10).ToDictionary((KeyValuePair<string, int> kv) => kv.Key, (KeyValuePair<string, int> kv) => kv.Value),
			ModelBreakdown = dictionary2,
			TabBreakdown = dictionary3,
			DailySessions = dictionary4,
			DailyTokens = dictionary5
		};
	}

	public static long GetFileSize()
	{
		return File.Exists(StatsFile) ? new FileInfo(StatsFile).Length : 0;
	}

	public static void Clear()
	{
		try
		{
			if (File.Exists(StatsFile))
			{
				File.Delete(StatsFile);
			}
		}
		catch (Exception ex)
		{
			LogService.Warn("통계 삭제 실패: " + ex.Message);
		}
	}
}
