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

namespace AxCopilot.Handlers;

/// <summary>
/// L25-1: 로컬 연락처 관리. "contact" 프리픽스로 사용합니다.
///
/// 예: contact                        → 전체 연락처 목록
///     contact 홍길동                 → 이름 검색
///     contact add 홍길동 개발팀 010-1234-5678 hong@company.com → 추가
///     contact del 홍길동             → 삭제
///     contact <부서명>               → 부서 필터
/// Enter → 이메일 또는 전화번호 클립보드 복사
/// 저장: %APPDATA%\AxCopilot\contacts.json
/// </summary>
public class ContactHandler : IActionHandler
{
    public string? Prefix => "contact";

    public PluginMetadata Metadata => new(
        "연락처",
        "로컬 연락처 관리 — 추가 · 검색 · 삭제 · 복사",
        "1.0",
        "AX");

    private static readonly string DataPath = System.IO.Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
        "AxCopilot", "contacts.json");

    private static readonly JsonSerializerOptions JsonOpts = new()
    {
        WriteIndented = true,
        Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
    };

    private sealed class Contact
    {
        [JsonPropertyName("name")]  public string Name  { get; set; } = "";
        [JsonPropertyName("dept")]  public string Dept  { get; set; } = "";
        [JsonPropertyName("phone")] public string Phone { get; set; } = "";
        [JsonPropertyName("email")] public string Email { get; set; } = "";
        [JsonPropertyName("memo")]  public string Memo  { get; set; } = "";
    }

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

        if (string.IsNullOrWhiteSpace(q))
        {
            items.Add(new LauncherItem(
                $"연락처 {contacts.Count}개",
                "contact add 이름 부서 010-xxxx-xxxx email@company.com",
                null, null, Symbol: "\uE8D4"));

            if (contacts.Count == 0)
            {
                items.Add(new LauncherItem("저장된 연락처가 없습니다",
                    "contact add 이름 부서 전화 이메일 로 추가하세요",
                    null, null, Symbol: "\uE946"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            foreach (var c in contacts)
                items.Add(MakeContactItem(c));

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

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

        // add 명령
        if (sub == "add")
        {
            var addPart = parts.Length > 1 ? parts[1].Trim() : "";
            if (string.IsNullOrWhiteSpace(addPart))
            {
                items.Add(new LauncherItem("이름을 입력하세요",
                    "예: contact add 홍길동 개발팀 010-1234-5678 hong@company.com",
                    null, null, Symbol: "\uE783"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            var (name, dept, phone, email, memo) = ParseAddArgs(addPart);
            if (string.IsNullOrWhiteSpace(name))
            {
                items.Add(new LauncherItem("이름을 입력하세요",
                    "예: contact add 홍길동 개발팀 010-1234-5678 hong@company.com",
                    null, null, Symbol: "\uE783"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            var encoded = $"{name}|{dept}|{phone}|{email}|{memo}";
            items.Add(new LauncherItem(
                $"연락처 추가: {name}",
                $"{dept}  {phone}  {email}  · Enter로 추가",
                null, ("add", encoded), Symbol: "\uE710"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // del 명령
        if (sub is "del" or "delete" or "remove")
        {
            var delName = parts.Length > 1 ? parts[1].Trim() : "";
            if (string.IsNullOrWhiteSpace(delName))
            {
                items.Add(new LauncherItem("삭제할 이름을 입력하세요",
                    "예: contact del 홍길동",
                    null, null, Symbol: "\uE783"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            var matches = contacts.Where(c =>
                c.Name.Contains(delName, StringComparison.OrdinalIgnoreCase)).ToList();

            if (matches.Count == 0)
            {
                items.Add(new LauncherItem($"'{delName}' 연락처를 찾을 수 없습니다", "",
                    null, null, Symbol: "\uE783"));
            }
            else
            {
                foreach (var c in matches)
                    items.Add(new LauncherItem(
                        $"{c.Name} 삭제",
                        $"{c.Dept}  {c.Phone}  {c.Email}  · Enter로 삭제",
                        null, ("del", c.Name), Symbol: "\uE8D4"));
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 검색: 이름, 부서, 메모 포함
        var byStartsWith = contacts
            .Where(c => c.Name.StartsWith(q, StringComparison.OrdinalIgnoreCase) ||
                        c.Dept.StartsWith(q, StringComparison.OrdinalIgnoreCase))
            .ToList();
        var byContains = contacts
            .Where(c => !byStartsWith.Contains(c) &&
                        (c.Name.Contains(q, StringComparison.OrdinalIgnoreCase) ||
                         c.Dept.Contains(q, StringComparison.OrdinalIgnoreCase) ||
                         c.Memo.Contains(q, StringComparison.OrdinalIgnoreCase)))
            .ToList();

        var results = byStartsWith.Concat(byContains).ToList();

        if (results.Count > 0)
        {
            items.Add(new LauncherItem($"'{q}' 검색 결과  {results.Count}개", "",
                null, null, Symbol: "\uE8D4"));
            foreach (var c in results)
                items.Add(MakeContactItem(c));
        }
        else
        {
            items.Add(new LauncherItem($"'{q}' 검색 결과 없음",
                "contact add 로 새 연락처를 추가하세요",
                null, null, Symbol: "\uE783"));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        switch (item.Data)
        {
            case ("copy_email", string email) when !string.IsNullOrWhiteSpace(email):
                CopyToClipboard(email);
                NotificationService.Notify("연락처", $"{email} 복사");
                break;

            case ("copy_phone", string phone) when !string.IsNullOrWhiteSpace(phone):
                CopyToClipboard(phone);
                NotificationService.Notify("연락처", $"{phone} 복사");
                break;

            case ("copy", string text) when !string.IsNullOrWhiteSpace(text):
                CopyToClipboard(text);
                NotificationService.Notify("연락처", $"{text} 복사");
                break;

            case ("add", string encoded):
                var addParts = encoded.Split('|');
                if (addParts.Length >= 5)
                {
                    var contact = new Contact
                    {
                        Name  = addParts[0],
                        Dept  = addParts[1],
                        Phone = addParts[2],
                        Email = addParts[3],
                        Memo  = addParts[4],
                    };
                    var list = LoadContacts();
                    list.RemoveAll(c => c.Name == contact.Name);
                    list.Add(contact);
                    SaveContacts(list);
                    NotificationService.Notify("연락처", $"{contact.Name} 추가됨");
                }
                break;

            case ("del", string name):
                var contacts = LoadContacts();
                var removed  = contacts.RemoveAll(c => c.Name == name);
                if (removed > 0)
                {
                    SaveContacts(contacts);
                    NotificationService.Notify("연락처", $"{name} 삭제됨");
                }
                break;
        }
        return Task.CompletedTask;
    }

    // ── 저장/불러오기 ─────────────────────────────────────────────────────────

    private static List<Contact> LoadContacts()
    {
        try
        {
            if (!System.IO.File.Exists(DataPath)) return new List<Contact>();
            var json = System.IO.File.ReadAllText(DataPath, System.Text.Encoding.UTF8);
            return JsonSerializer.Deserialize<List<Contact>>(json, JsonOpts) ?? new List<Contact>();
        }
        catch { return new List<Contact>(); }
    }

    private static void SaveContacts(List<Contact> contacts)
    {
        try
        {
            System.IO.Directory.CreateDirectory(System.IO.Path.GetDirectoryName(DataPath)!);
            System.IO.File.WriteAllText(DataPath,
                JsonSerializer.Serialize(contacts, JsonOpts),
                System.Text.Encoding.UTF8);
        }
        catch { /* 비핵심 */ }
    }

    // ── 헬퍼 ─────────────────────────────────────────────────────────────────

    private static LauncherItem MakeContactItem(Contact c)
    {
        var title = $"{c.Name}";
        if (!string.IsNullOrWhiteSpace(c.Dept)) title += $"  ·  {c.Dept}";
        var sub   = "";
        if (!string.IsNullOrWhiteSpace(c.Phone)) sub += c.Phone;
        if (!string.IsNullOrWhiteSpace(c.Email)) sub += (sub.Length > 0 ? "  |  " : "") + c.Email;

        // 복사 우선순위: email > phone > name
        (string action, string value) data;
        if (!string.IsNullOrWhiteSpace(c.Email))
            data = ("copy_email", c.Email);
        else if (!string.IsNullOrWhiteSpace(c.Phone))
            data = ("copy_phone", c.Phone);
        else
            data = ("copy", c.Name);

        return new LauncherItem(title, sub, null, data, Symbol: "\uE8D4");
    }

    private static (string name, string dept, string phone, string email, string memo)
        ParseAddArgs(string addPart)
    {
        var tokens = addPart.Split(' ', StringSplitOptions.RemoveEmptyEntries);
        if (tokens.Length == 0) return ("", "", "", "", "");

        var name  = tokens[0];
        var dept  = "";
        var phone = "";
        var email = "";
        var memoTokens = new List<string>();

        for (var i = 1; i < tokens.Length; i++)
        {
            var t = tokens[i];
            if (string.IsNullOrWhiteSpace(phone) && IsPhoneLike(t))
                phone = t;
            else if (string.IsNullOrWhiteSpace(email) && t.Contains('@'))
                email = t;
            else if (string.IsNullOrWhiteSpace(dept) && i == 1)
                dept = t;
            else
                memoTokens.Add(t);
        }

        return (name, dept, phone, email, string.Join(" ", memoTokens));
    }

    private static bool IsPhoneLike(string s)
    {
        var stripped = s.Replace("-", "").Replace(" ", "");
        return stripped.Length >= 9 && stripped.All(c => char.IsDigit(c));
    }

    private static void CopyToClipboard(string text)
    {
        try
        {
            Application.Current.Dispatcher.Invoke(() => Clipboard.SetText(text));
        }
        catch { }
    }
}
