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

namespace AxCopilot.Handlers;

/// <summary>
/// L10-4: Lorem Ipsum / 더미 텍스트 생성기 핸들러. "lorem" 프리픽스로 사용합니다.
///
/// 예: lorem              → 1단락 생성 (기본)
///     lorem 3            → 3단락 생성
///     lorem words 20     → 단어 20개
///     lorem sentences 5  → 문장 5개
///     lorem ko           → 한국어 더미 텍스트 1단락
///     lorem ko 3         → 한국어 더미 텍스트 3단락
///     lorem email 5      → 더미 이메일 주소 5개
///     lorem name 5       → 더미 이름 5개 (한국어)
/// Enter → 결과를 클립보드에 복사.
/// </summary>
public class LoremHandler : IActionHandler
{
    public string? Prefix => "lorem";

    public PluginMetadata Metadata => new(
        "Lorem",
        "더미 텍스트 생성기 — Lorem Ipsum · 한국어 · 이메일 · 이름",
        "1.0",
        "AX");

    // ── Lorem Ipsum 단어 풀 ─────────────────────────────────────────────────
    private static readonly string[] LoremWords =
    [
        "lorem", "ipsum", "dolor", "sit", "amet", "consectetur", "adipiscing", "elit",
        "sed", "do", "eiusmod", "tempor", "incididunt", "ut", "labore", "et", "dolore",
        "magna", "aliqua", "enim", "ad", "minim", "veniam", "quis", "nostrud",
        "exercitation", "ullamco", "laboris", "nisi", "aliquip", "ex", "ea", "commodo",
        "consequat", "duis", "aute", "irure", "in", "reprehenderit", "voluptate",
        "velit", "esse", "cillum", "eu", "fugiat", "nulla", "pariatur", "excepteur",
        "sint", "occaecat", "cupidatat", "non", "proident", "sunt", "culpa", "qui",
        "officia", "deserunt", "mollit", "anim", "id", "est", "laborum", "perspiciatis",
        "unde", "omnis", "iste", "natus", "error", "voluptatem", "accusantium",
        "doloremque", "laudantium", "totam", "rem", "aperiam", "eaque", "ipsa", "quae",
        "ab", "illo", "inventore", "veritatis", "quasi", "architecto", "beatae", "vitae",
        "dicta", "explicabo", "nemo", "ipsam", "quia", "voluptas", "aspernatur", "aut",
        "odit", "fugit", "consequuntur", "magni", "dolores", "ratione", "sequi",
        "nesciunt", "neque", "porro", "quisquam", "dolorem", "numquam", "eius", "modi",
        "temporibus", "incidunt", "magnam", "aliquam", "quaerat", "minima", "nostrum",
        "exercitationem", "ullam", "corporis", "suscipit", "laboriosam", "nisi",
        "aliquid", "commodi", "consequatur", "quidem", "rerum", "facilis",
    ];

    // ── 한국어 더미 단어 풀 ──────────────────────────────────────────────────
    private static readonly string[] KorWords =
    [
        "가나다라", "마바사아", "자차카타", "파하", "데이터", "처리", "시스템", "네트워크",
        "소프트웨어", "알고리즘", "데이터베이스", "인터페이스", "프레임워크", "모듈", "클래스",
        "메서드", "함수", "변수", "구조체", "배열", "목록", "사전", "집합", "스택", "큐",
        "트리", "그래프", "정렬", "탐색", "분석", "설계", "구현", "테스트", "배포", "운영",
        "서비스", "플랫폼", "클라우드", "컨테이너", "가상화", "보안", "암호화", "인증", "권한",
        "로그", "모니터링", "알림", "이벤트", "트랜잭션", "세션", "쿠키", "토큰", "키",
        "값", "객체", "인스턴스", "프로세스", "스레드", "비동기", "병렬", "동기화", "잠금",
        "버퍼", "캐시", "인덱스", "쿼리", "뷰", "프로시저", "스키마", "테이블", "컬럼",
        "행", "열", "기본키", "외래키", "조인", "집계", "필터", "정렬", "그룹화", "분류",
    ];

    private static readonly string[] KorSentenceStarters =
    [
        "이 시스템은", "해당 모듈은", "기능을 구현하면", "데이터를 처리하는",
        "네트워크 연결이", "서비스가 시작되면", "사용자 인터페이스는", "알고리즘이",
        "처리 과정에서", "설계 단계에서", "구현 방식은", "테스트 결과",
    ];

    private static readonly string[] KorSentenceEnders =
    [
        "처리됩니다.", "구현되어 있습니다.", "필요합니다.", "중요한 역할을 합니다.",
        "확인할 수 있습니다.", "설계되어 있습니다.", "활용됩니다.", "반환됩니다.",
        "저장됩니다.", "업데이트됩니다.", "삭제됩니다.", "초기화됩니다.",
    ];

    // ── 더미 이름/이메일 데이터 ───────────────────────────────────────────────
    private static readonly string[] KorLastNames  = ["김", "이", "박", "최", "정", "강", "조", "윤", "장", "임", "한", "오", "서", "신", "권", "황", "안", "송", "류", "전"];
    private static readonly string[] KorFirstNames = ["민준", "서연", "예준", "서현", "도윤", "지우", "시우", "수아", "지호", "하은", "준서", "하린", "건우", "소연", "현우", "지민", "우진", "지유", "연우", "채원"];
    private static readonly string[] EmailDomains  = ["example.com", "test.co.kr", "dummy.net", "sample.org", "mock.io", "placeholder.dev"];

    private static readonly Random Rng = new();

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

        if (string.IsNullOrWhiteSpace(q))
        {
            var para = GenerateParagraph(false);
            items.Add(new LauncherItem(
                "Lorem Ipsum 1단락",
                para.Length > 80 ? para[..80] + "…" : para,
                null,
                ("copy", para),
                Symbol: "\uE8BD"));
            items.Add(new LauncherItem("lorem 3",           "3단락 생성",          null, null, Symbol: "\uE8BD"));
            items.Add(new LauncherItem("lorem words 20",    "단어 20개",           null, null, Symbol: "\uE8BD"));
            items.Add(new LauncherItem("lorem sentences 3", "문장 3개",            null, null, Symbol: "\uE8BD"));
            items.Add(new LauncherItem("lorem ko",          "한국어 더미 텍스트",   null, null, Symbol: "\uE8BD"));
            items.Add(new LauncherItem("lorem email 5",     "더미 이메일 5개",     null, null, Symbol: "\uE8BD"));
            items.Add(new LauncherItem("lorem name 5",      "더미 이름 5개",       null, null, Symbol: "\uE8BD"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        var parts = q.Split(' ', StringSplitOptions.RemoveEmptyEntries);
        var sub   = parts[0].ToLowerInvariant();

        switch (sub)
        {
            case "words":
            case "word":
            case "w":
            {
                var cnt = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 500) : 20;
                var text = GenerateWords(cnt, false);
                items.Add(new LauncherItem(
                    $"단어 {cnt}개",
                    text.Length > 80 ? text[..80] + "…" : text,
                    null, ("copy", text), Symbol: "\uE8BD"));
                break;
            }

            case "sentences":
            case "sentence":
            case "s":
            {
                var cnt  = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 50) : 5;
                var text = GenerateSentences(cnt, false);
                items.Add(new LauncherItem(
                    $"문장 {cnt}개",
                    text.Length > 80 ? text[..80] + "…" : text,
                    null, ("copy", text), Symbol: "\uE8BD"));
                break;
            }

            case "ko":
            case "kor":
            case "korean":
            {
                var cnt  = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 10) : 1;
                var text = GenerateParagraphs(cnt, true);
                items.Add(new LauncherItem(
                    $"한국어 더미 텍스트 {cnt}단락",
                    text.Length > 80 ? text[..80] + "…" : text,
                    null, ("copy", text), Symbol: "\uE8BD"));
                break;
            }

            case "email":
            {
                var cnt = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 20) : 5;
                var emails = Enumerable.Range(0, cnt).Select(_ => GenerateEmail()).ToList();
                var all    = string.Join("\n", emails);
                items.Add(new LauncherItem(
                    $"더미 이메일 {cnt}개",
                    "전체 복사: Enter",
                    null, ("copy", all), Symbol: "\uE8BD"));
                foreach (var email in emails)
                    items.Add(new LauncherItem(email, "Enter 복사", null, ("copy", email), Symbol: "\uE8BD"));
                break;
            }

            case "name":
            case "names":
            {
                var cnt   = parts.Length > 1 && int.TryParse(parts[1], out var n) ? Math.Clamp(n, 1, 20) : 5;
                var names = Enumerable.Range(0, cnt).Select(_ => GenerateKorName()).ToList();
                var all   = string.Join("\n", names);
                items.Add(new LauncherItem(
                    $"더미 이름 {cnt}개",
                    "전체 복사: Enter",
                    null, ("copy", all), Symbol: "\uE8BD"));
                foreach (var name in names)
                    items.Add(new LauncherItem(name, "한국어 이름  · Enter 복사", null, ("copy", name), Symbol: "\uE8BD"));
                break;
            }

            default:
            {
                // 숫자 단독 → 단락 수
                var cnt = int.TryParse(sub, out var n) ? Math.Clamp(n, 1, 10) : 1;
                var text = GenerateParagraphs(cnt, false);
                items.Add(new LauncherItem(
                    $"Lorem Ipsum {cnt}단락",
                    text.Length > 80 ? text[..80] + "…" : text,
                    null, ("copy", text), Symbol: "\uE8BD"));
                break;
            }
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is ("copy", string text))
        {
            try
            {
                System.Windows.Application.Current.Dispatcher.Invoke(
                    () => Clipboard.SetText(text));
                NotificationService.Notify("Lorem", "클립보드에 복사했습니다.");
            }
            catch { /* 비핵심 */ }
        }
        return Task.CompletedTask;
    }

    // ── 생성 헬퍼 ─────────────────────────────────────────────────────────────

    private static string GenerateParagraphs(int count, bool korean)
    {
        var paras = Enumerable.Range(0, count).Select(_ => GenerateParagraph(korean));
        return string.Join("\n\n", paras);
    }

    private static string GenerateParagraph(bool korean)
    {
        var sentenceCount = Rng.Next(4, 8);
        return GenerateSentences(sentenceCount, korean);
    }

    private static string GenerateSentences(int count, bool korean)
    {
        var sb = new StringBuilder();
        for (var i = 0; i < count; i++)
        {
            if (i > 0) sb.Append(' ');
            sb.Append(GenerateSentence(korean));
        }
        return sb.ToString();
    }

    private static string GenerateSentence(bool korean)
    {
        if (korean)
        {
            var starter = KorSentenceStarters[Rng.Next(KorSentenceStarters.Length)];
            var wordCnt = Rng.Next(3, 8);
            var words   = Enumerable.Range(0, wordCnt).Select(_ => KorWords[Rng.Next(KorWords.Length)]);
            var ender   = KorSentenceEnders[Rng.Next(KorSentenceEnders.Length)];
            return $"{starter} {string.Join(" ", words)} {ender}";
        }
        else
        {
            var wordCnt = Rng.Next(6, 15);
            var words   = Enumerable.Range(0, wordCnt).Select((_, idx) =>
            {
                var w = LoremWords[Rng.Next(LoremWords.Length)];
                return idx == 0 ? char.ToUpper(w[0]) + w[1..] : w;
            });
            return string.Join(" ", words) + ".";
        }
    }

    private static string GenerateWords(int count, bool korean)
    {
        var pool = korean ? KorWords : LoremWords;
        return string.Join(" ", Enumerable.Range(0, count).Select(_ => pool[Rng.Next(pool.Length)]));
    }

    private static string GenerateEmail()
    {
        var first  = LoremWords[Rng.Next(LoremWords.Length)];
        var second = LoremWords[Rng.Next(LoremWords.Length)];
        var num    = Rng.Next(10, 999);
        var domain = EmailDomains[Rng.Next(EmailDomains.Length)];
        return $"{first}.{second}{num}@{domain}";
    }

    private static string GenerateKorName()
    {
        var last  = KorLastNames[Rng.Next(KorLastNames.Length)];
        var first = KorFirstNames[Rng.Next(KorFirstNames.Length)];
        return last + first;
    }
}
