using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Windows;
using System.Windows.Threading;

namespace AxCopilot.Services;

public class AgentTriggerService : IDisposable
{
	private readonly SettingsService _settings;

	private FileSystemWatcher? _fileWatcher;

	private DispatcherTimer? _scheduleTimer;

	private readonly List<TriggerRule> _rules = new List<TriggerRule>();

	private bool _disposed;

	public Action<string, string>? OnTriggerFired { get; set; }

	public IReadOnlyList<TriggerRule> Rules => _rules;

	public AgentTriggerService(SettingsService settings)
	{
		_settings = settings;
	}

	public void Start()
	{
		LoadRules();
		StartFileWatcher();
		StartScheduleTimer();
		LogService.Info($"에이전트 트리거 서비스 시작: {_rules.Count}개 규칙");
	}

	public void Reload()
	{
		Stop();
		Start();
	}

	public void Stop()
	{
		_fileWatcher?.Dispose();
		_fileWatcher = null;
		DispatcherTimer? scheduleTimer = _scheduleTimer;
		if (scheduleTimer != null)
		{
			scheduleTimer.Stop();
		}
	}

	private void LoadRules()
	{
		_rules.Clear();
		string path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "triggers.json");
		if (!File.Exists(path))
		{
			return;
		}
		try
		{
			string json = File.ReadAllText(path);
			List<TriggerRule> list = JsonSerializer.Deserialize<List<TriggerRule>>(json);
			if (list != null)
			{
				_rules.AddRange(list.Where((TriggerRule r) => r.Enabled));
			}
		}
		catch (Exception ex)
		{
			LogService.Warn("트리거 규칙 로드 실패: " + ex.Message);
		}
	}

	private void StartFileWatcher()
	{
		List<TriggerRule> fileRules = _rules.Where((TriggerRule r) => r.Type == "file_change").ToList();
		if (fileRules.Count == 0)
		{
			return;
		}
		string workFolder = _settings.Settings.Llm.WorkFolder;
		if (string.IsNullOrEmpty(workFolder) || !Directory.Exists(workFolder))
		{
			return;
		}
		_fileWatcher = new FileSystemWatcher(workFolder)
		{
			IncludeSubdirectories = true,
			NotifyFilter = (NotifyFilters.FileName | NotifyFilters.LastWrite),
			EnableRaisingEvents = true
		};
		DateTime lastTrigger = DateTime.MinValue;
		_fileWatcher.Changed += delegate(object _, FileSystemEventArgs e)
		{
			if ((DateTime.Now - lastTrigger).TotalSeconds < 5.0)
			{
				return;
			}
			foreach (TriggerRule rule in fileRules)
			{
				if (MatchesPattern(e.FullPath, rule.Pattern))
				{
					lastTrigger = DateTime.Now;
					string prompt = rule.Prompt.Replace("{file}", e.FullPath).Replace("{name}", e.Name ?? "");
					Application current = Application.Current;
					if (current != null)
					{
						((DispatcherObject)current).Dispatcher.BeginInvoke((Delegate)(Action)delegate
						{
							OnTriggerFired?.Invoke(rule.Name, prompt);
						}, Array.Empty<object>());
					}
					break;
				}
			}
		};
	}

	private void StartScheduleTimer()
	{
		//IL_0058: Unknown result type (might be due to invalid IL or missing references)
		//IL_005d: Unknown result type (might be due to invalid IL or missing references)
		//IL_0077: Expected O, but got Unknown
		List<TriggerRule> scheduleRules = _rules.Where((TriggerRule r) => r.Type == "schedule").ToList();
		if (scheduleRules.Count == 0)
		{
			return;
		}
		_scheduleTimer = new DispatcherTimer
		{
			Interval = TimeSpan.FromMinutes(1.0)
		};
		_scheduleTimer.Tick += delegate
		{
			DateTime now = DateTime.Now;
			foreach (TriggerRule item in scheduleRules)
			{
				if (ShouldRunSchedule(item, now))
				{
					item.LastRun = now;
					OnTriggerFired?.Invoke(item.Name, item.Prompt);
				}
			}
		};
		_scheduleTimer.Start();
	}

	private static bool MatchesPattern(string filePath, string? pattern)
	{
		if (string.IsNullOrEmpty(pattern))
		{
			return true;
		}
		if (pattern.StartsWith("*."))
		{
			return filePath.EndsWith(pattern.Substring(1, pattern.Length - 1), StringComparison.OrdinalIgnoreCase);
		}
		return filePath.Contains(pattern, StringComparison.OrdinalIgnoreCase);
	}

	private static bool ShouldRunSchedule(TriggerRule rule, DateTime now)
	{
		if (rule.LastRun.HasValue && (now - rule.LastRun.Value).TotalMinutes < (double)(rule.IntervalMinutes ?? 60))
		{
			return false;
		}
		if (rule.ActiveHourStart.HasValue && now.Hour < rule.ActiveHourStart.Value)
		{
			return false;
		}
		if (rule.ActiveHourEnd.HasValue && now.Hour >= rule.ActiveHourEnd.Value)
		{
			return false;
		}
		return true;
	}

	public void FireManual(string ruleName)
	{
		TriggerRule triggerRule = _rules.FirstOrDefault((TriggerRule r) => r.Name == ruleName);
		if (triggerRule != null)
		{
			OnTriggerFired?.Invoke(triggerRule.Name, triggerRule.Prompt);
		}
	}

	public void Dispose()
	{
		if (!_disposed)
		{
			_disposed = true;
			Stop();
		}
	}
}
