using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// 프로젝트 스캐폴딩 핸들러. "scaffold" 프리픽스로 사용합니다.
/// 로컬 템플릿으로 프로젝트 폴더 구조를 일괄 생성합니다.
/// 예: scaffold                  → 등록된 템플릿 목록
///     scaffold webapi           → "webapi" 템플릿 적용
///     scaffold add [이름]       → 현재 폴더 구조를 템플릿으로 저장 (별도 도구에서)
/// 템플릿 저장 위치: %APPDATA%\AxCopilot\templates\[이름].json
/// Enter → 대상 경로를 물어본 후 생성.
/// </summary>
public class ScaffoldHandler : IActionHandler
{
    public string? Prefix => "scaffold";

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

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

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

    public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
    {
        var q = query.Trim();

        // 사용자 정의 템플릿 로드
        var userTemplates = LoadUserTemplates();
        var allTemplates = BuiltInTemplates.Concat(userTemplates).ToList();

        if (string.IsNullOrWhiteSpace(q))
        {
            var items = allTemplates.Select(t => new LauncherItem(
                $"[{t.Name}]  {t.Description}",
                $"{t.Paths.Length}개 폴더/파일  ·  Enter → 대상 경로 입력 후 생성",
                null, t,
                Symbol: Symbols.Folder)).ToList<LauncherItem>();

            items.Insert(0, new LauncherItem(
                "프로젝트 스캐폴딩",
                $"총 {allTemplates.Count}개 템플릿  ·  이름을 입력해 필터링",
                null, null, Symbol: Symbols.Info));

            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // "경로 템플릿" 형태 감지 (경로에 \ 또는 / 포함)
        if (q.Contains('\\') || q.Contains('/'))
        {
            var spaceIdx = q.LastIndexOf(' ');
            if (spaceIdx > 0)
            {
                var targetPath = q[..spaceIdx].Trim();
                var templateName = q[(spaceIdx + 1)..].Trim();
                var tmpl = allTemplates.FirstOrDefault(t =>
                    t.Name.Equals(templateName, StringComparison.OrdinalIgnoreCase));

                if (tmpl != null)
                {
                    return Task.FromResult<IEnumerable<LauncherItem>>(
                    [
                        new LauncherItem(
                            $"[{tmpl.Name}] → {targetPath}",
                            $"{tmpl.Paths.Length}개 폴더/파일 생성  ·  Enter로 실행",
                            null, ValueTuple.Create(targetPath, tmpl),
                            Symbol: Symbols.Save)
                    ]);
                }
            }
        }

        // 필터링
        var filtered = allTemplates.Where(t =>
            t.Name.Contains(q, StringComparison.OrdinalIgnoreCase) ||
            t.Description.Contains(q, StringComparison.OrdinalIgnoreCase));

        var result = filtered.Select(t =>
        {
            var preview = string.Join(", ", t.Paths.Take(4));
            if (t.Paths.Length > 4) preview += $" ... (+{t.Paths.Length - 4})";
            return new LauncherItem(
                $"[{t.Name}]  {t.Description}",
                $"{preview}  ·  사용법: scaffold [대상경로] {t.Name}",
                null, t,
                Symbol: Symbols.Folder);
        }).ToList<LauncherItem>();

        if (!result.Any())
        {
            result.Add(new LauncherItem(
                $"'{q}'에 해당하는 템플릿 없음",
                "scaffold 으로 전체 목록 확인",
                null, null, Symbol: Symbols.Warning));
        }

        return Task.FromResult<IEnumerable<LauncherItem>>(result);
    }

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is ValueTuple<string, ScaffoldTemplate> data)
        {
            var (targetPath, template) = data;
            return CreateStructure(targetPath, template);
        }

        if (item.Data is ScaffoldTemplate tmpl)
        {
            // 클립보드에 사용법 복사
            var usage = $"scaffold [대상경로] {tmpl.Name}";
            try { System.Windows.Application.Current?.Dispatcher.Invoke(
                () => System.Windows.Clipboard.SetText(usage)); }
            catch (Exception) { }
        }

        return Task.CompletedTask;
    }

    private static Task CreateStructure(string basePath, ScaffoldTemplate template)
    {
        try
        {
            int created = 0;
            foreach (var path in template.Paths)
            {
                var fullPath = Path.Combine(basePath, path.Replace('/', Path.DirectorySeparatorChar));

                if (path.EndsWith('/') || path.EndsWith('\\') || !Path.HasExtension(path))
                {
                    Directory.CreateDirectory(fullPath);
                }
                else
                {
                    Directory.CreateDirectory(Path.GetDirectoryName(fullPath)!);
                    if (!File.Exists(fullPath))
                        File.WriteAllText(fullPath, "");
                }
                created++;
            }
            NotificationService.Notify("스캐폴딩 완료",
                $"[{template.Name}] {created}개 항목 생성 → {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;

        foreach (var file in Directory.GetFiles(TemplateDir, "*.json"))
        {
            ScaffoldTemplate? tmpl = null;
            try
            {
                var json = File.ReadAllText(file);
                tmpl = JsonSerializer.Deserialize<ScaffoldTemplate>(json);
            }
            catch (Exception) { }
            if (tmpl != null) yield return tmpl;
        }
    }

    internal record ScaffoldTemplate(
        [property: JsonPropertyName("name")] string Name,
        [property: JsonPropertyName("description")] string Description,
        [property: JsonPropertyName("paths")] string[] Paths);
}
