using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using AxCopilot.SDK;
using AxCopilot.Services;

namespace AxCopilot.Handlers;

public class ScaffoldHandler : IActionHandler
{
	internal record ScaffoldTemplate([property: JsonPropertyName("name")] string Name, [property: JsonPropertyName("description")] string Description, [property: JsonPropertyName("paths")] string[] Paths);

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

	private static readonly ScaffoldTemplate[] BuiltInTemplates = new ScaffoldTemplate[5]
	{
		new ScaffoldTemplate("webapi", "Web API 프로젝트", new string[8] { "src/Controllers/", "src/Models/", "src/Services/", "src/Middleware/", "tests/", "docs/", "README.md", ".gitignore" }),
		new ScaffoldTemplate("console", "콘솔 애플리케이션", new string[5] { "src/", "src/Core/", "src/Services/", "tests/", "README.md" }),
		new ScaffoldTemplate("wpf", "WPF 데스크톱 앱", new string[8] { "src/Views/", "src/ViewModels/", "src/Models/", "src/Services/", "src/Themes/", "src/Assets/", "tests/", "docs/" }),
		new ScaffoldTemplate("data", "데이터 파이프라인", new string[9] { "src/Extractors/", "src/Transformers/", "src/Loaders/", "config/", "scripts/", "tests/", "data/input/", "data/output/", "README.md" }),
		new ScaffoldTemplate("docs", "문서 프로젝트", new string[5] { "docs/", "images/", "templates/", "README.md", "CHANGELOG.md" })
	};

	public string? Prefix => "scaffold";

	public PluginMetadata Metadata => new PluginMetadata("Scaffold", "프로젝트 스캐폴딩 — scaffold", "1.0", "AX");

	public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
	{
		string q = query.Trim();
		IEnumerable<ScaffoldTemplate> second = LoadUserTemplates();
		List<ScaffoldTemplate> list = BuiltInTemplates.Concat(second).ToList();
		if (string.IsNullOrWhiteSpace(q))
		{
			List<LauncherItem> list2 = list.Select((ScaffoldTemplate t) => new LauncherItem("[" + t.Name + "]  " + t.Description, $"{t.Paths.Length}개 폴더/파일  ·  Enter → 대상 경로 입력 후 생성", null, t, null, "\ue8b7")).ToList();
			list2.Insert(0, new LauncherItem("프로젝트 스캐폴딩", $"총 {list.Count}개 템플릿  ·  이름을 입력해 필터링", null, null, null, "\ue946"));
			return Task.FromResult((IEnumerable<LauncherItem>)list2);
		}
		if (q.Contains('\\') || q.Contains('/'))
		{
			int num = q.LastIndexOf(' ');
			if (num > 0)
			{
				string text = q.Substring(0, num).Trim();
				string text2 = q;
				int num2 = num + 1;
				string templateName = text2.Substring(num2, text2.Length - num2).Trim();
				ScaffoldTemplate scaffoldTemplate = list.FirstOrDefault((ScaffoldTemplate t) => t.Name.Equals(templateName, StringComparison.OrdinalIgnoreCase));
				if (scaffoldTemplate != null)
				{
					return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("[" + scaffoldTemplate.Name + "] → " + text, $"{scaffoldTemplate.Paths.Length}개 폴더/파일 생성  ·  Enter로 실행", null, ValueTuple.Create(text, scaffoldTemplate), null, "\ue74e")));
				}
			}
		}
		IEnumerable<ScaffoldTemplate> source = list.Where((ScaffoldTemplate t) => t.Name.Contains(q, StringComparison.OrdinalIgnoreCase) || t.Description.Contains(q, StringComparison.OrdinalIgnoreCase));
		List<LauncherItem> list3 = source.Select(delegate(ScaffoldTemplate t)
		{
			string text3 = string.Join(", ", t.Paths.Take(4));
			if (t.Paths.Length > 4)
			{
				text3 += $" ... (+{t.Paths.Length - 4})";
			}
			return new LauncherItem("[" + t.Name + "]  " + t.Description, text3 + "  ·  사용법: scaffold [대상경로] " + t.Name, null, t, null, "\ue8b7");
		}).ToList();
		if (!list3.Any())
		{
			list3.Add(new LauncherItem("'" + q + "'에 해당하는 템플릿 없음", "scaffold 으로 전체 목록 확인", null, null, null, "\ue7ba"));
		}
		return Task.FromResult((IEnumerable<LauncherItem>)list3);
	}

	public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
	{
		if (!(item.Data is (string, ScaffoldTemplate) tuple))
		{
			if (item.Data is ScaffoldTemplate scaffoldTemplate)
			{
				string usage = "scaffold [대상경로] " + scaffoldTemplate.Name;
				try
				{
					Application current = Application.Current;
					if (current != null)
					{
						((DispatcherObject)current).Dispatcher.Invoke((Action)delegate
						{
							Clipboard.SetText(usage);
						});
					}
				}
				catch
				{
				}
			}
			return Task.CompletedTask;
		}
		var (basePath, template) = tuple;
		return CreateStructure(basePath, template);
	}

	private static Task CreateStructure(string basePath, ScaffoldTemplate template)
	{
		try
		{
			int num = 0;
			string[] paths = template.Paths;
			foreach (string text in paths)
			{
				string path = Path.Combine(basePath, text.Replace('/', Path.DirectorySeparatorChar));
				if (text.EndsWith('/') || text.EndsWith('\\') || !Path.HasExtension(text))
				{
					Directory.CreateDirectory(path);
				}
				else
				{
					Directory.CreateDirectory(Path.GetDirectoryName(path));
					if (!File.Exists(path))
					{
						File.WriteAllText(path, "");
					}
				}
				num++;
			}
			NotificationService.Notify("스캐폴딩 완료", $"[{template.Name}] {num}개 항목 생성 → {basePath}");
		}
		catch (Exception ex)
		{
			LogService.Error("스캐폴딩 실패: " + ex.Message);
			NotificationService.Notify("AX Copilot", "스캐폴딩 실패: " + ex.Message);
		}
		return Task.CompletedTask;
	}

	private static IEnumerable<ScaffoldTemplate> LoadUserTemplates()
	{
		if (!Directory.Exists(TemplateDir))
		{
			yield break;
		}
		string[] files = Directory.GetFiles(TemplateDir, "*.json");
		foreach (string file in files)
		{
			ScaffoldTemplate tmpl = null;
			try
			{
				string json = File.ReadAllText(file);
				tmpl = JsonSerializer.Deserialize<ScaffoldTemplate>(json);
			}
			catch
			{
			}
			if (tmpl != null)
			{
				yield return tmpl;
			}
		}
	}
}
