using System.Diagnostics;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// 파일 일괄 이름변경 핸들러. "rename" 프리픽스로 사용합니다.
/// 지정된 폴더 내 파일을 패턴으로 일괄 이름변경합니다.
/// 예: rename                           → 사용법 안내
///     rename C:\work\*.xlsx            → 해당 폴더의 xlsx 파일 목록
///     rename C:\work\*.xlsx 보고서_{n}  → 보고서_1.xlsx, 보고서_2.xlsx ...
/// {n}=순번, {date}=오늘 날짜, {orig}=원본명
/// Enter → 실행 전 미리보기, Shift+Enter → 실행.
/// </summary>
public class RenameHandler : IActionHandler
{
    public string? Prefix => "rename";

    public PluginMetadata Metadata => new(
        "Rename",
        "파일 일괄 이름변경 — rename",
        "1.0",
        "AX");

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

        if (string.IsNullOrWhiteSpace(q))
        {
            return Task.FromResult<IEnumerable<LauncherItem>>(
            [
                new LauncherItem(
                    "파일 일괄 이름변경",
                    "rename [폴더\\패턴] [새이름 템플릿]",
                    null, null, Symbol: Symbols.Rename),
                new LauncherItem(
                    "사용 예시",
                    "rename C:\\work\\*.xlsx 보고서_{n}  →  보고서_1.xlsx, 보고서_2.xlsx ...",
                    null, null, Symbol: Symbols.Info),
                new LauncherItem(
                    "변수: {n} 순번, {date} 날짜, {orig} 원본명",
                    "rename D:\\photos\\*.jpg {date}_{n}  →  2026-03-27_1.jpg ...",
                    null, null, Symbol: Symbols.Info),
            ]);
        }

        // 파싱: [경로\패턴] [템플릿]
        var parts = q.Split(' ', 2, StringSplitOptions.TrimEntries);
        var pattern = parts[0];
        var template = parts.Length > 1 ? parts[1] : null;

        // 경로 분리
        var dir = Path.GetDirectoryName(pattern);
        var glob = Path.GetFileName(pattern);

        if (string.IsNullOrWhiteSpace(dir) || !Directory.Exists(dir))
        {
            return Task.FromResult<IEnumerable<LauncherItem>>(
            [
                new LauncherItem(
                    "폴더를 찾을 수 없습니다",
                    $"경로: {dir ?? "(비어 있음)"}",
                    null, null, Symbol: Symbols.Warning)
            ]);
        }

        string[] files;
        try { files = Directory.GetFiles(dir, glob); }
        catch (Exception) { files = Array.Empty<string>(); }

        if (files.Length == 0)
        {
            return Task.FromResult<IEnumerable<LauncherItem>>(
            [
                new LauncherItem(
                    "일치하는 파일이 없습니다",
                    $"패턴: {glob}  ·  폴더: {dir}",
                    null, null, Symbol: Symbols.Warning)
            ]);
        }

        Array.Sort(files);

        // 템플릿이 없으면 파일 목록만 표시
        if (string.IsNullOrWhiteSpace(template))
        {
            var items = files.Take(10).Select((f, i) => new LauncherItem(
                Path.GetFileName(f),
                dir,
                null, null,
                Symbol: Symbols.File)).ToList<LauncherItem>();

            items.Insert(0, new LauncherItem(
                $"총 {files.Length}개 파일 발견",
                "뒤에 새 이름 템플릿을 추가하세요 (예: 보고서_{n})",
                null, null, Symbol: Symbols.Info));

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

        // 미리보기 생성
        var today = DateTime.Today.ToString("yyyy-MM-dd");
        var previews = new List<(string From, string To)>();
        for (int i = 0; i < files.Length; i++)
        {
            var origName = Path.GetFileNameWithoutExtension(files[i]);
            var ext = Path.GetExtension(files[i]);
            var newName = template
                .Replace("{n}", (i + 1).ToString())
                .Replace("{date}", today)
                .Replace("{orig}", origName);
            // 확장자 자동 유지 (템플릿에 확장자가 없으면)
            if (!Path.HasExtension(newName))
                newName += ext;
            previews.Add((Path.GetFileName(files[i]), newName));
        }

        var result = new List<LauncherItem>();

        // 실행 항목
        result.Add(new LauncherItem(
            $"총 {files.Length}개 파일 이름변경 실행",
            $"Enter로 실행  ·  {previews[0].From} → {previews[0].To} ...",
            null, ValueTuple.Create(dir, files, previews.Select(p => p.To).ToArray()),
            Symbol: Symbols.Rename));

        // 미리보기 (최대 8개)
        foreach (var (from, to) in previews.Take(8))
        {
            result.Add(new LauncherItem(
                $"{from}  →  {to}",
                "미리보기",
                null, null,
                Symbol: Symbols.File));
        }

        if (files.Length > 8)
        {
            result.Add(new LauncherItem(
                $"... 외 {files.Length - 8}개",
                "",
                null, null,
                Symbol: Symbols.Info));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is not ValueTuple<string, string[], string[]> data)
            return Task.CompletedTask;

        var (dir, files, newNames) = data;
        int renamed = 0;
        int failed = 0;

        for (int i = 0; i < files.Length && i < newNames.Length; i++)
        {
            try
            {
                var dest = Path.Combine(dir, newNames[i]);
                if (File.Exists(dest))
                {
                    failed++;
                    continue;
                }
                File.Move(files[i], dest);
                renamed++;
            }
            catch (Exception)
            {
                failed++;
            }
        }

        var msg = failed > 0
            ? $"{renamed}개 이름변경 완료, {failed}개 실패 (이미 존재하거나 접근 불가)"
            : $"{renamed}개 파일 이름변경 완료";
        NotificationService.Notify("AX Copilot", msg);
        return Task.CompletedTask;
    }
}
