using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Services;

namespace AxCopilot.Handlers;

/// <summary>
/// L25-3: 자주 쓰는 업무 문구 모음. "phrase" 프리픽스로 사용합니다.
///
/// 예: phrase                 → 카테고리 목록
///     phrase 인사            → 인사 문구 목록
///     phrase 보고            → 보고/발표 문구
///     phrase 요청            → 요청/협조 문구
///     phrase 마무리          → 마무리/감사 문구
///     phrase <검색어>        → 전체 검색
/// Enter → 문구 클립보드 복사
/// </summary>
public class PhraseHandler : IActionHandler
{
    public string? Prefix => "phrase";

    public PluginMetadata Metadata => new(
        "업무 문구",
        "자주 쓰는 업무 문구 — 인사·보고·요청·마무리·승인·회의·사과",
        "1.0",
        "AX");

    private sealed record PhraseEntry(string Text, string Category, string CategoryKey);

    private static readonly List<PhraseEntry> _phrases = BuildPhrases();

    private static readonly (string Key, string Display, string[] Aliases)[] _categories =
    [
        ("greeting",  "인사",     ["인사", "greeting"]),
        ("report",    "보고",     ["보고", "보고서", "report"]),
        ("request",   "요청",     ["요청", "협조", "request"]),
        ("closing",   "마무리",   ["마무리", "감사", "closing"]),
        ("approval",  "승인결재", ["승인", "결재", "approval"]),
        ("meeting",   "회의",     ["회의", "미팅", "meeting"]),
        ("apology",   "사과지연", ["사과", "지연", "사죄", "apology"]),
    ];

    private static List<PhraseEntry> BuildPhrases()
    {
        var list = new List<PhraseEntry>();

        // 인사 (greeting)
        void G(string t) => list.Add(new PhraseEntry(t, "인사", "greeting"));
        G("안녕하세요. [이름]입니다.");
        G("수고 많으십니다.");
        G("오랜만에 연락드립니다.");
        G("처음 뵙겠습니다. 잘 부탁드립니다.");
        G("바쁘신 와중에 연락드려 죄송합니다.");
        G("항상 감사드립니다.");
        G("늦은 시간에 연락드려 죄송합니다.");
        G("좋은 하루 보내세요.");
        G("주말 잘 보내세요.");
        G("휴가 잘 다녀오세요.");

        // 보고 (report)
        void R(string t) => list.Add(new PhraseEntry(t, "보고", "report"));
        R("말씀하신 대로 처리하겠습니다.");
        R("현재 검토 중에 있습니다.");
        R("확인 후 말씀드리겠습니다.");
        R("금일 중으로 처리하겠습니다.");
        R("해당 건은 [날짜]까지 완료 예정입니다.");
        R("진행 상황을 공유드립니다.");
        R("결과 보고드립니다.");
        R("관련하여 추가 검토가 필요합니다.");
        R("이슈 사항이 발생하여 공유드립니다.");
        R("문제없이 완료되었습니다.");

        // 요청 (request)
        void Req(string t) => list.Add(new PhraseEntry(t, "요청", "request"));
        Req("검토 부탁드립니다.");
        Req("회신 부탁드립니다.");
        Req("확인 부탁드립니다.");
        Req("협조 부탁드립니다.");
        Req("아래 내용 확인 후 승인 부탁드립니다.");
        Req("첨부 파일 확인 부탁드립니다.");
        Req("가능한 빠른 시일 내 처리 부탁드립니다.");
        Req("[날짜]까지 회신 주시면 감사하겠습니다.");
        Req("필요한 사항 있으시면 알려주세요.");
        Req("문의 사항은 언제든지 연락 주세요.");

        // 마무리 (closing)
        void C(string t) => list.Add(new PhraseEntry(t, "마무리", "closing"));
        C("감사합니다.");
        C("수고하셨습니다.");
        C("도움 주셔서 감사합니다.");
        C("빠른 처리 감사드립니다.");
        C("앞으로도 잘 부탁드립니다.");
        C("이상입니다.");
        C("이상으로 보고를 마치겠습니다.");
        C("궁금하신 점은 언제든 문의 주세요.");
        C("좋은 결과 있기를 바랍니다.");
        C("다시 한번 감사드립니다.");

        // 승인결재 (approval)
        void A(string t) => list.Add(new PhraseEntry(t, "승인결재", "approval"));
        A("검토 후 승인 부탁드립니다.");
        A("위 내용으로 진행해도 될까요?");
        A("담당자 확인 후 피드백 주세요.");
        A("위와 같이 결정되었음을 알려드립니다.");
        A("아래와 같이 변경합니다.");
        A("이의 없으시면 그대로 진행하겠습니다.");
        A("검토 의견 부탁드립니다.");

        // 회의 (meeting)
        void M(string t) => list.Add(new PhraseEntry(t, "회의", "meeting"));
        M("오늘 회의 내용을 공유드립니다.");
        M("다음 회의는 [날짜]에 진행 예정입니다.");
        M("회의 참석 부탁드립니다.");
        M("회의 장소 및 일정을 안내드립니다.");
        M("회의록 공유드립니다.");
        M("다음 주 [요일] [시간]에 미팅 가능하신가요?");
        M("일정 조율 부탁드립니다.");
        M("화상 회의 링크 공유드립니다.");
        M("회의 아젠다 공유드립니다.");

        // 사과/지연 (apology)
        void Ap(string t) => list.Add(new PhraseEntry(t, "사과지연", "apology"));
        Ap("처리가 늦어져 죄송합니다.");
        Ap("불편을 드려 죄송합니다.");
        Ap("확인이 늦었습니다. 죄송합니다.");
        Ap("오류가 발생하여 사과드립니다.");
        Ap("빠른 처리가 어려운 점 양해 부탁드립니다.");
        Ap("답변이 늦어 죄송합니다.");

        return list;
    }

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

        if (string.IsNullOrWhiteSpace(q))
        {
            // 카테고리 목록 표시
            items.Add(new LauncherItem(
                "업무 문구 카테고리",
                "phrase <카테고리>  또는  phrase <검색어>",
                null, null, Symbol: "\uE8A0"));

            foreach (var (key, display, _) in _categories)
            {
                var count = _phrases.Count(p => p.CategoryKey == key);
                items.Add(new LauncherItem(
                    $"{display}  ({count}개)",
                    $"phrase {display}  →  문구 목록",
                    null, ("category", key), Symbol: "\uE8A0"));
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        var kw = q.ToLowerInvariant();

        // 카테고리 키워드 매칭
        foreach (var (key, display, aliases) in _categories)
        {
            if (aliases.Any(a => a.Equals(q, StringComparison.OrdinalIgnoreCase) ||
                                 a.Contains(q, StringComparison.OrdinalIgnoreCase)))
            {
                var catPhrases = _phrases.Where(p => p.CategoryKey == key).ToList();
                items.Add(new LauncherItem(
                    $"{display}  ({catPhrases.Count}개)",
                    "Enter → 클립보드 복사",
                    null, null, Symbol: "\uE8A0"));
                foreach (var p in catPhrases)
                    items.Add(new LauncherItem(p.Text, p.Category,
                        null, ("copy", p.Text), Symbol: "\uE8A0"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }
        }

        // 전체 검색
        var results = _phrases
            .Where(p => p.Text.Contains(q, StringComparison.OrdinalIgnoreCase))
            .ToList();

        if (results.Count > 0)
        {
            items.Add(new LauncherItem(
                $"'{q}' 검색 결과  {results.Count}개",
                "Enter → 클립보드 복사",
                null, null, Symbol: "\uE8A0"));
            foreach (var p in results)
                items.Add(new LauncherItem(p.Text, p.Category,
                    null, ("copy", p.Text), Symbol: "\uE8A0"));
        }
        else
        {
            items.Add(new LauncherItem($"'{q}' 검색 결과 없음",
                "카테고리: 인사 / 보고 / 요청 / 마무리 / 승인결재 / 회의 / 사과지연",
                null, null, Symbol: "\uE783"));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is ("copy", string text) && !string.IsNullOrWhiteSpace(text))
        {
            try
            {
                Application.Current.Dispatcher.Invoke(() => Clipboard.SetText(text));
                NotificationService.Notify("문구", "클립보드에 복사했습니다.");
            }
            catch { }
        }
        return Task.CompletedTask;
    }
}
