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

namespace AxCopilot.Handlers;

/// <summary>
/// L18-4: IT·개발 약어 사전 핸들러. "abbr" 프리픽스로 사용합니다.
///
/// 예: abbr                   → 주요 약어 목록
///     abbr api                → API 뜻 + 설명
///     abbr crud               → CRUD 약어 풀이
///     abbr rest               → REST 설명
///     abbr http               → HTTP 약어 목록
/// Enter → 약어 또는 뜻을 클립보드에 복사.
/// </summary>
public class AbbrHandler : IActionHandler
{
    public string? Prefix => "abbr";

    public PluginMetadata Metadata => new(
        "Abbr",
        "IT·개발 약어 사전 — API · CRUD · REST · HTTP · SQL 등 내장",
        "1.0",
        "AX");

    private record AbbrEntry(string Short, string Full, string Description, string Category);

    // ── 내장 약어 사전 (~150개) ───────────────────────────────────────────────
    private static readonly AbbrEntry[] Entries =
    [
        // 웹/네트워크
        new("API",     "Application Programming Interface",         "소프트웨어 간 통신 규격",                          "웹/네트워크"),
        new("REST",    "Representational State Transfer",           "HTTP 기반 아키텍처 스타일",                         "웹/네트워크"),
        new("HTTP",    "HyperText Transfer Protocol",               "웹 통신 프로토콜",                                  "웹/네트워크"),
        new("HTTPS",   "HTTP Secure",                               "TLS/SSL로 암호화된 HTTP",                           "웹/네트워크"),
        new("HTML",    "HyperText Markup Language",                 "웹 페이지 마크업 언어",                             "웹/네트워크"),
        new("CSS",     "Cascading Style Sheets",                    "웹 스타일 시트 언어",                               "웹/네트워크"),
        new("URL",     "Uniform Resource Locator",                  "인터넷 자원 주소",                                  "웹/네트워크"),
        new("URI",     "Uniform Resource Identifier",               "자원 식별자 (URL의 상위 개념)",                     "웹/네트워크"),
        new("DNS",     "Domain Name System",                        "도메인 ↔ IP 변환 시스템",                           "웹/네트워크"),
        new("IP",      "Internet Protocol",                         "인터넷 패킷 전송 프로토콜",                         "웹/네트워크"),
        new("TCP",     "Transmission Control Protocol",             "신뢰성 연결형 전송 프로토콜",                       "웹/네트워크"),
        new("UDP",     "User Datagram Protocol",                    "비연결형 전송 프로토콜",                            "웹/네트워크"),
        new("SSH",     "Secure Shell",                              "원격 보안 접속 프로토콜",                           "웹/네트워크"),
        new("FTP",     "File Transfer Protocol",                    "파일 전송 프로토콜",                                "웹/네트워크"),
        new("SMTP",    "Simple Mail Transfer Protocol",             "이메일 전송 프로토콜",                              "웹/네트워크"),
        new("CDN",     "Content Delivery Network",                  "콘텐츠 분산 배포 네트워크",                         "웹/네트워크"),
        new("VPN",     "Virtual Private Network",                   "가상 사설 네트워크",                                "웹/네트워크"),
        new("NAT",     "Network Address Translation",               "사설↔공인 IP 주소 변환",                            "웹/네트워크"),
        new("CORS",    "Cross-Origin Resource Sharing",             "브라우저 교차 출처 리소스 공유",                    "웹/네트워크"),
        new("SSE",     "Server-Sent Events",                        "서버→클라이언트 단방향 스트림",                     "웹/네트워크"),
        new("WebSocket","WebSocket Protocol",                       "양방향 실시간 통신 프로토콜",                       "웹/네트워크"),
        new("gRPC",    "Google Remote Procedure Call",              "프로토콜 버퍼 기반 RPC 프레임워크",                 "웹/네트워크"),
        new("GraphQL", "Graph Query Language",                      "API 쿼리 언어 (Facebook 개발)",                     "웹/네트워크"),
        new("SOAP",    "Simple Object Access Protocol",             "XML 기반 웹 서비스 프로토콜",                       "웹/네트워크"),
        new("WSDL",    "Web Services Description Language",         "웹 서비스 인터페이스 설명 언어",                    "웹/네트워크"),
        new("TLS",     "Transport Layer Security",                  "암호화 통신 프로토콜 (SSL 후속)",                   "웹/네트워크"),
        new("SSL",     "Secure Sockets Layer",                      "암호화 통신 프로토콜 (TLS의 전신)",                 "웹/네트워크"),
        new("OAuth",   "Open Authorization",                        "위임 인증 표준 프로토콜",                           "웹/네트워크"),
        new("MIME",    "Multipurpose Internet Mail Extensions",     "이메일·웹 콘텐츠 타입 표준",                        "웹/네트워크"),

        // 개발/프로그래밍
        new("CRUD",    "Create Read Update Delete",                 "기본 데이터 처리 4가지 연산",                       "개발"),
        new("OOP",     "Object-Oriented Programming",              "객체 지향 프로그래밍",                              "개발"),
        new("SOLID",   "Single responsibility Open/closed Liskov Interface-segregation Dependency-inversion",
                                                                     "객체지향 5가지 설계 원칙",                          "개발"),
        new("DRY",     "Don't Repeat Yourself",                     "코드 중복 최소화 원칙",                             "개발"),
        new("KISS",    "Keep It Simple, Stupid",                    "단순하게 유지하라 원칙",                            "개발"),
        new("YAGNI",   "You Aren't Gonna Need It",                  "필요할 때만 구현하라 원칙",                         "개발"),
        new("TDD",     "Test-Driven Development",                   "테스트 주도 개발 방법론",                           "개발"),
        new("BDD",     "Behavior-Driven Development",               "행동 주도 개발 방법론",                             "개발"),
        new("DDD",     "Domain-Driven Design",                      "도메인 주도 설계",                                  "개발"),
        new("MVC",     "Model-View-Controller",                     "UI 아키텍처 패턴",                                  "개발"),
        new("MVP",     "Model-View-Presenter",                      "MVC의 변형, Presenter가 View와 Model 중재",         "개발"),
        new("MVVM",    "Model-View-ViewModel",                      "WPF·모바일 아키텍처 패턴",                         "개발"),
        new("SRP",     "Single Responsibility Principle",           "단일 책임 원칙 (SOLID의 S)",                        "개발"),
        new("OCP",     "Open/Closed Principle",                     "개방/폐쇄 원칙 (SOLID의 O)",                        "개발"),
        new("LSP",     "Liskov Substitution Principle",             "리스코프 치환 원칙 (SOLID의 L)",                    "개발"),
        new("ISP",     "Interface Segregation Principle",           "인터페이스 분리 원칙 (SOLID의 I)",                  "개발"),
        new("DIP",     "Dependency Inversion Principle",            "의존성 역전 원칙 (SOLID의 D)",                      "개발"),
        new("IoC",     "Inversion of Control",                      "제어 역전 (프레임워크 핵심 개념)",                  "개발"),
        new("DI",      "Dependency Injection",                      "의존성 주입 패턴",                                  "개발"),
        new("AOP",     "Aspect-Oriented Programming",               "관점 지향 프로그래밍",                              "개발"),
        new("FP",      "Functional Programming",                    "함수형 프로그래밍",                                 "개발"),
        new("DSL",     "Domain-Specific Language",                  "특정 도메인 전용 언어",                             "개발"),
        new("SDK",     "Software Development Kit",                  "소프트웨어 개발 도구 모음",                         "개발"),
        new("IDE",     "Integrated Development Environment",        "통합 개발 환경",                                    "개발"),
        new("CLI",     "Command Line Interface",                    "명령줄 인터페이스",                                 "개발"),
        new("GUI",     "Graphical User Interface",                  "그래픽 사용자 인터페이스",                          "개발"),
        new("UI",      "User Interface",                            "사용자 인터페이스",                                 "개발"),
        new("UX",      "User Experience",                           "사용자 경험",                                       "개발"),
        new("SPA",     "Single Page Application",                   "단일 페이지 애플리케이션",                          "개발"),
        new("SSR",     "Server-Side Rendering",                     "서버 사이드 렌더링",                                "개발"),
        new("CSR",     "Client-Side Rendering",                     "클라이언트 사이드 렌더링",                          "개발"),
        new("PWA",     "Progressive Web App",                       "프로그레시브 웹 앱",                                "개발"),
        new("CDK",     "Cloud Development Kit",                     "클라우드 인프라 코드 개발 도구",                    "개발"),
        new("ORM",     "Object-Relational Mapping",                 "객체-관계형 데이터베이스 매핑",                     "개발"),
        new("REPL",    "Read-Eval-Print Loop",                      "대화형 프로그래밍 환경",                            "개발"),
        new("GC",      "Garbage Collection",                        "자동 메모리 회수",                                  "개발"),
        new("JIT",     "Just-In-Time Compilation",                  "실행 시점 컴파일",                                  "개발"),
        new("AOT",     "Ahead-Of-Time Compilation",                 "사전 컴파일",                                       "개발"),
        new("WASM",    "WebAssembly",                               "브라우저용 바이너리 형식",                          "개발"),
        new("AST",     "Abstract Syntax Tree",                      "추상 구문 트리",                                    "개발"),
        new("LSP",     "Language Server Protocol",                  "언어 분석 서버 표준 프로토콜",                      "개발"),

        // 데이터베이스
        new("SQL",     "Structured Query Language",                 "관계형 DB 쿼리 언어",                               "DB"),
        new("NoSQL",   "Not Only SQL",                              "비관계형 데이터베이스 총칭",                        "DB"),
        new("ACID",    "Atomicity Consistency Isolation Durability", "DB 트랜잭션 4가지 성질",                           "DB"),
        new("CAP",     "Consistency Availability Partition-tolerance","분산 DB 설계 이론 (셋 중 2개만 보장)",            "DB"),
        new("ETL",     "Extract Transform Load",                    "데이터 추출·변환·적재 프로세스",                    "DB"),
        new("OLTP",    "Online Transaction Processing",             "트랜잭션 처리 중심 DB",                             "DB"),
        new("OLAP",    "Online Analytical Processing",              "분석 처리 중심 DB (데이터 웨어하우스)",             "DB"),
        new("DDL",     "Data Definition Language",                  "DB 구조 정의 SQL (CREATE/ALTER/DROP)",              "DB"),
        new("DML",     "Data Manipulation Language",                "데이터 조작 SQL (SELECT/INSERT/UPDATE/DELETE)",     "DB"),
        new("DCL",     "Data Control Language",                     "접근 권한 SQL (GRANT/REVOKE)",                      "DB"),

        // 보안
        new("JWT",     "JSON Web Token",                            "JSON 기반 인증 토큰 표준",                          "보안"),
        new("RBAC",    "Role-Based Access Control",                 "역할 기반 접근 제어",                               "보안"),
        new("ABAC",    "Attribute-Based Access Control",            "속성 기반 접근 제어",                               "보안"),
        new("MFA",     "Multi-Factor Authentication",               "다중 인증",                                         "보안"),
        new("2FA",     "Two-Factor Authentication",                 "이중 인증",                                         "보안"),
        new("XSS",     "Cross-Site Scripting",                      "악성 스크립트 삽입 공격",                           "보안"),
        new("CSRF",    "Cross-Site Request Forgery",                "교차 사이트 요청 위조 공격",                        "보안"),
        new("SQL Injection", "SQL Injection Attack",                "SQL 쿼리 삽입 공격",                                "보안"),
        new("OWASP",   "Open Web Application Security Project",     "웹 보안 가이드라인 기관",                           "보안"),
        new("CVE",     "Common Vulnerabilities and Exposures",      "공개 보안 취약점 DB",                               "보안"),
        new("HTTPS",   "HTTP Secure",                               "TLS로 암호화된 HTTP",                               "보안"),
        new("AES",     "Advanced Encryption Standard",              "대칭키 암호화 표준 (128/192/256bit)",               "보안"),
        new("RSA",     "Rivest–Shamir–Adleman",                     "공개키 비대칭 암호화 알고리즘",                     "보안"),
        new("HMAC",    "Hash-based Message Authentication Code",    "해시 기반 메시지 인증 코드",                        "보안"),
        new("PKI",     "Public Key Infrastructure",                 "공개키 인프라",                                     "보안"),

        // 클라우드/인프라
        new("AWS",     "Amazon Web Services",                       "아마존 클라우드 서비스",                            "클라우드"),
        new("GCP",     "Google Cloud Platform",                     "구글 클라우드 서비스",                              "클라우드"),
        new("SaaS",    "Software as a Service",                     "구독형 소프트웨어 서비스",                          "클라우드"),
        new("PaaS",    "Platform as a Service",                     "플랫폼 서비스",                                     "클라우드"),
        new("IaaS",    "Infrastructure as a Service",               "인프라 서비스",                                     "클라우드"),
        new("FaaS",    "Function as a Service",                     "서버리스 함수 서비스",                              "클라우드"),
        new("K8s",     "Kubernetes",                                "컨테이너 오케스트레이션 플랫폼",                    "클라우드"),
        new("CI/CD",   "Continuous Integration/Continuous Delivery","지속적 통합/배포 파이프라인",                       "클라우드"),
        new("IaC",     "Infrastructure as Code",                    "코드로 관리하는 인프라",                            "클라우드"),
        new("VPC",     "Virtual Private Cloud",                     "가상 사설 클라우드 네트워크",                       "클라우드"),
        new("SLA",     "Service Level Agreement",                   "서비스 수준 계약 (가용성 보장)",                    "클라우드"),
        new("SLO",     "Service Level Objective",                   "서비스 수준 목표",                                  "클라우드"),
        new("RTO",     "Recovery Time Objective",                   "복구 목표 시간",                                    "클라우드"),
        new("RPO",     "Recovery Point Objective",                  "복구 목표 지점",                                    "클라우드"),
        new("CDN",     "Content Delivery Network",                  "콘텐츠 분산 배포 네트워크",                         "클라우드"),
        new("ECS",     "Elastic Container Service",                 "AWS 컨테이너 관리 서비스",                          "클라우드"),
        new("ECR",     "Elastic Container Registry",                "AWS 컨테이너 이미지 저장소",                        "클라우드"),
        new("EKS",     "Elastic Kubernetes Service",                "AWS 관리형 Kubernetes",                             "클라우드"),

        // AI/ML
        new("AI",      "Artificial Intelligence",                   "인공지능",                                          "AI/ML"),
        new("ML",      "Machine Learning",                          "머신러닝",                                          "AI/ML"),
        new("DL",      "Deep Learning",                             "딥러닝",                                            "AI/ML"),
        new("LLM",     "Large Language Model",                      "대규모 언어 모델",                                  "AI/ML"),
        new("NLP",     "Natural Language Processing",               "자연어 처리",                                       "AI/ML"),
        new("CNN",     "Convolutional Neural Network",              "합성곱 신경망",                                     "AI/ML"),
        new("RNN",     "Recurrent Neural Network",                  "순환 신경망",                                       "AI/ML"),
        new("GAN",     "Generative Adversarial Network",            "생성적 적대 신경망",                                "AI/ML"),
        new("RAG",     "Retrieval-Augmented Generation",            "검색 증강 생성 (LLM + 검색)",                       "AI/ML"),
        new("RLHF",    "Reinforcement Learning from Human Feedback","인간 피드백 강화학습",                              "AI/ML"),
        new("GPT",     "Generative Pre-trained Transformer",        "생성형 사전학습 변환기 (OpenAI)",                   "AI/ML"),
        new("BERT",    "Bidirectional Encoder Representations from Transformers","양방향 트랜스포머 언어 모델",          "AI/ML"),
        new("SFT",     "Supervised Fine-Tuning",                    "지도 학습 파인튜닝",                                "AI/ML"),
        new("LoRA",    "Low-Rank Adaptation",                       "저순위 행렬 파인튜닝 기법",                         "AI/ML"),
        new("MCP",     "Model Context Protocol",                    "LLM 외부 도구 연결 표준 프로토콜",                  "AI/ML"),
        new("CoT",     "Chain of Thought",                          "사고 단계 명시 프롬프팅",                           "AI/ML"),

        // 데이터 형식
        new("JSON",    "JavaScript Object Notation",                "경량 데이터 교환 형식",                             "데이터형식"),
        new("XML",     "Extensible Markup Language",                "확장 가능 마크업 언어",                             "데이터형식"),
        new("YAML",    "YAML Ain't Markup Language",                "사람이 읽기 쉬운 데이터 직렬화 형식",              "데이터형식"),
        new("TOML",    "Tom's Obvious, Minimal Language",           "설정 파일 전용 경량 형식",                          "데이터형식"),
        new("CSV",     "Comma-Separated Values",                    "쉼표 구분 데이터 형식",                             "데이터형식"),
        new("TSV",     "Tab-Separated Values",                      "탭 구분 데이터 형식",                               "데이터형식"),
        new("Protobuf","Protocol Buffers",                          "구글 이진 직렬화 형식",                             "데이터형식"),
        new("Avro",    "Apache Avro",                               "Hadoop 생태계 이진 직렬화",                         "데이터형식"),
        new("Parquet", "Apache Parquet",                            "열 지향 이진 데이터 형식",                          "데이터형식"),
        new("Base64",  "Base 64 encoding",                          "이진 데이터 텍스트 인코딩 (64진수)",                "데이터형식"),

        // 버전 관리/협업
        new("VCS",     "Version Control System",                    "버전 관리 시스템",                                  "협업"),
        new("SCM",     "Source Code Management",                    "소스 코드 관리",                                    "협업"),
        new("PR",      "Pull Request",                              "코드 병합 요청 (GitHub 용어)",                      "협업"),
        new("MR",      "Merge Request",                             "코드 병합 요청 (GitLab 용어)",                      "협업"),
        new("LGTM",    "Looks Good To Me",                          "코드 리뷰 승인 표현",                               "협업"),
        new("WIP",     "Work In Progress",                          "진행 중 작업",                                      "협업"),
        new("RFC",     "Request for Comments",                      "의견 요청 문서 (표준화 프로세스)",                  "협업"),
        new("POC",     "Proof of Concept",                          "개념 검증",                                         "협업"),
        new("MVP",     "Minimum Viable Product",                    "최소 기능 제품",                                    "협업"),
        new("KPI",     "Key Performance Indicator",                 "핵심 성과 지표",                                    "협업"),
        new("OKR",     "Objectives and Key Results",                "목표 및 핵심 결과",                                 "협업"),
        new("SOP",     "Standard Operating Procedure",              "표준 운영 절차",                                    "협업"),
    ];

    private static readonly string[] Categories = Entries.Select(e => e.Category).Distinct().ToArray();

    // ── 커스텀 약어 ───────────────────────────────────────────────────────────
    private static readonly string CustomPath = System.IO.Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
        "AxCopilot", "abbr_custom.json");

    private sealed class CustomAbbr
    {
        [JsonPropertyName("short")]  public string Short       { get; set; } = "";
        [JsonPropertyName("full")]   public string Full        { get; set; } = "";
        [JsonPropertyName("desc")]   public string Description { get; set; } = "";
        [JsonPropertyName("cat")]    public string Category    { get; set; } = "사용자정의";
    }

    private static List<CustomAbbr> LoadCustom()
    {
        try {
            if (System.IO.File.Exists(CustomPath))
                return JsonSerializer.Deserialize<List<CustomAbbr>>(
                    System.IO.File.ReadAllText(CustomPath)) ?? [];
        } catch { }
        return [];
    }

    private static void SaveCustom(List<CustomAbbr> list)
    {
        System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(CustomPath)!);
        System.IO.File.WriteAllText(CustomPath, JsonSerializer.Serialize(list,
            new JsonSerializerOptions { WriteIndented = true,
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping }));
    }

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

        // ── 서브커맨드 처리 ───────────────────────────────────────────────────
        // abbr custom → 사용자 정의 약어 목록
        if (q.Equals("custom", StringComparison.OrdinalIgnoreCase))
        {
            var customList = LoadCustom();
            if (customList.Count == 0)
            {
                items.Add(new LauncherItem("사용자 정의 약어 없음",
                    "abbr add <약어> <풀이> [설명]  으로 추가하세요",
                    null, null, Symbol: "\uE82D"));
            }
            else
            {
                items.Add(new LauncherItem($"사용자 정의 약어  {customList.Count}개", "", null, null, Symbol: "\uE82D"));
                foreach (var c in customList)
                    items.Add(new LauncherItem(c.Short,
                        $"{c.Full}  ·  {c.Description}",
                        null, ("copy", $"{c.Short}: {c.Full}"), Symbol: "\uE82D"));
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // abbr add <약어> <풀이> [설명]
        if (q.StartsWith("add ", StringComparison.OrdinalIgnoreCase))
        {
            var rest  = q[4..].Trim();
            var parts = rest.Split(' ', 3, StringSplitOptions.RemoveEmptyEntries);
            if (parts.Length < 2)
            {
                items.Add(new LauncherItem("사용법: abbr add <약어> <풀이> [설명]",
                    "예: abbr add ROI 투자수익률 Return on Investment",
                    null, null, Symbol: "\uE82D"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }
            var abbr = parts[0].ToUpper();
            var full = parts[1];
            var desc = parts.Length > 2 ? parts[2] : "";
            var encoded = $"{abbr}|{full}|{desc}";
            items.Add(new LauncherItem($"약어 추가: {abbr}  =  {full}",
                desc.Length > 0 ? desc : "Enter: 저장",
                null, ("add", encoded), Symbol: "\uE82D"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // abbr del <약어>
        if (q.StartsWith("del ", StringComparison.OrdinalIgnoreCase))
        {
            var abbr = q[4..].Trim().ToUpper();
            if (string.IsNullOrEmpty(abbr))
            {
                items.Add(new LauncherItem("사용법: abbr del <약어>",
                    "예: abbr del ROI",
                    null, null, Symbol: "\uE82D"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }
            items.Add(new LauncherItem($"약어 삭제: {abbr}",
                "Enter: 삭제 확인",
                null, ("del", abbr), Symbol: "\uE82D"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        if (string.IsNullOrWhiteSpace(q))
        {
            items.Add(new LauncherItem($"IT·개발 약어 사전  {Entries.Length}개",
                "abbr <약어>  예: abbr api / abbr crud / abbr jwt",
                null, null, Symbol: "\uE82D"));
            // 커스텀 약어 추가 안내
            items.Add(new LauncherItem("abbr add <약어> <풀이>  — 나만의 약어 추가",
                "예: abbr add ROI 투자수익률",
                null, null, Symbol: "\uE82D"));
            items.Add(new LauncherItem("── 카테고리 ──", "", null, null, Symbol: "\uE82D"));
            foreach (var cat in Categories)
            {
                var cnt = Entries.Count(e => e.Category == cat);
                items.Add(new LauncherItem(cat, $"{cnt}개  ·  abbr {cat}로 목록 보기",
                    null, null, Symbol: "\uE82D"));
            }
            // 자주 쓰는 약어 샘플
            items.Add(new LauncherItem("── 자주 쓰는 약어 ──", "", null, null, Symbol: "\uE82D"));
            var popular = new[] { "API", "CRUD", "REST", "JWT", "SQL", "CI/CD", "TDD", "OOP" };
            foreach (var p in popular)
            {
                var e = Entries.FirstOrDefault(x => x.Short.Equals(p, StringComparison.OrdinalIgnoreCase));
                if (e != null)
                    items.Add(MakeAbbrItem(e));
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 카테고리 검색
        if (Categories.Any(c => c.Equals(q, StringComparison.OrdinalIgnoreCase)))
        {
            var catEntries = Entries.Where(e => e.Category.Equals(q, StringComparison.OrdinalIgnoreCase)).ToList();
            items.Add(new LauncherItem($"{q}  {catEntries.Count}개", "", null, null, Symbol: "\uE82D"));
            foreach (var e in catEntries)
                items.Add(MakeAbbrItem(e));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 약어 검색 (정확 일치 우선, 그 다음 부분 일치) — 내장 + 커스텀 통합
        var customSearch = LoadCustom();
        var customEntries = customSearch.Select(c => new AbbrEntry(c.Short, c.Full, c.Description, c.Category)).ToList();
        var allEntries    = Entries.Concat(customEntries).ToList();

        var exact = allEntries.Where(e =>
            e.Short.Equals(q, StringComparison.OrdinalIgnoreCase)).ToList();

        var partial = allEntries.Where(e =>
            !exact.Contains(e) &&
            (e.Short.Contains(q, StringComparison.OrdinalIgnoreCase) ||
             e.Full.Contains(q, StringComparison.OrdinalIgnoreCase) ||
             e.Description.Contains(q, StringComparison.OrdinalIgnoreCase))).ToList();

        var all = exact.Concat(partial).ToList();

        if (all.Count == 0)
        {
            items.Add(new LauncherItem($"'{q}' 약어를 찾을 수 없습니다",
                "카테고리: " + string.Join(", ", Categories),
                null, null, Symbol: "\uE946"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        if (exact.Count == 1)
        {
            // 정확 일치 1개 → 상세 표시
            var e = exact[0];
            items.Add(new LauncherItem($"{e.Short}  =  {e.Full}",
                e.Description, null, ("copy", $"{e.Short}: {e.Full}"), Symbol: "\uE82D"));
            items.Add(new LauncherItem("약어",    e.Short,       null, ("copy", e.Short),       Symbol: "\uE82D"));
            items.Add(new LauncherItem("원문",    e.Full,        null, ("copy", e.Full),         Symbol: "\uE82D"));
            items.Add(new LauncherItem("설명",    e.Description, null, ("copy", e.Description),  Symbol: "\uE82D"));
            items.Add(new LauncherItem("카테고리",e.Category,    null, null,                      Symbol: "\uE82D"));
        }
        else
        {
            items.Add(new LauncherItem($"'{q}' 검색 결과  {all.Count}개", "", null, null, Symbol: "\uE82D"));
            foreach (var e in all.Take(30))
                items.Add(MakeAbbrItem(e));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        switch (item.Data)
        {
            case ("copy", string text):
                try
                {
                    System.Windows.Application.Current.Dispatcher.Invoke(
                        () => Clipboard.SetText(text));
                    NotificationService.Notify("Abbr", "클립보드에 복사했습니다.");
                }
                catch { }
                break;

            case ("add", string encoded):
                var parts = encoded.Split('|', 3);
                var custom = LoadCustom();
                custom.RemoveAll(c => c.Short.Equals(parts[0], StringComparison.OrdinalIgnoreCase));
                custom.Add(new CustomAbbr {
                    Short = parts[0].ToUpper(),
                    Full = parts.Length > 1 ? parts[1] : "",
                    Description = parts.Length > 2 ? parts[2] : "",
                });
                SaveCustom(custom);
                NotificationService.Notify("약어", $"{parts[0].ToUpper()} 등록 완료");
                break;

            case ("del", string abbr):
                var customDel = LoadCustom();
                customDel.RemoveAll(c => c.Short.Equals(abbr, StringComparison.OrdinalIgnoreCase));
                SaveCustom(customDel);
                NotificationService.Notify("약어", $"{abbr.ToUpper()} 삭제 완료");
                break;
        }
        return Task.CompletedTask;
    }

    private static LauncherItem MakeAbbrItem(AbbrEntry e) =>
        new(e.Short,
            $"{e.Full}  ·  {e.Description}",
            null, ("copy", $"{e.Short}: {e.Full}"), Symbol: "\uE82D");
}
