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

namespace AxCopilot.Handlers;

/// <summary>
/// L14-3: 팁·할인·분할 계산기 핸들러. "tip" 프리픽스로 사용합니다.
///
/// 예: tip 50000             → 50,000원에 대한 팁 퍼센트별 계산
///     tip 50000 15          → 15% 팁 계산
///     tip 50000 / 4         → 4명 분할
///     tip 50000 15 4        → 15% 팁 포함 4명 분할
///     tip 50000 off 20      → 20% 할인가 계산
///     tip 50000 vat         → 부가가치세 10% 계산
/// Enter → 결과를 클립보드에 복사.
/// </summary>
public class TipHandler : IActionHandler
{
    public string? Prefix => "tip";

    public PluginMetadata Metadata => new(
        "Tip",
        "팁·할인·분할 계산기 — 팁 % · 할인 · VAT · 인원 분할",
        "1.0",
        "AX");

    private static readonly int[] DefaultTipRates = [10, 15, 18, 20, 25];
    private static readonly int[] DefaultDiscountRates = [5, 10, 15, 20, 30, 50];

    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("팁·할인·분할 계산기",
                "예: tip 50000  /  tip 50000 15  /  tip 50000 off 20  /  tip 50000 / 4",
                null, null, Symbol: "\uE8F0"));
            items.Add(new LauncherItem("tip 50000",        "50,000원 팁 계산",    null, null, Symbol: "\uE8F0"));
            items.Add(new LauncherItem("tip 50000 15 4",   "15% 팁 + 4명 분할",  null, null, Symbol: "\uE8F0"));
            items.Add(new LauncherItem("tip 50000 off 20", "20% 할인가",          null, null, Symbol: "\uE8F0"));
            items.Add(new LauncherItem("tip 50000 vat",    "VAT 10% 계산",        null, null, Symbol: "\uE8F0"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        var parts = q.Split(' ', StringSplitOptions.RemoveEmptyEntries);

        // 금액 파싱 (쉼표 제거)
        if (!TryParseAmount(parts[0], out var amount))
        {
            items.Add(new LauncherItem("금액 형식 오류",
                "예: tip 50000  또는  tip 50,000", null, null, Symbol: "\uE783"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 서브커맨드 분기
        if (parts.Length >= 2)
        {
            var sub2 = parts[1].ToLowerInvariant();

            // 할인: tip 50000 off 20
            if (sub2 is "off" or "discount" or "할인")
            {
                var rate = parts.Length >= 3 && TryParseAmount(parts[2], out var r) ? r : 10;
                items.AddRange(BuildDiscountItems(amount, (double)rate));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            // VAT: tip 50000 vat [rate]
            if (sub2 is "vat" or "세금" or "tax")
            {
                var rate = parts.Length >= 3 && TryParseAmount(parts[2], out var r) ? (double)r : 10.0;
                items.AddRange(BuildVatItems(amount, rate));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            // 분할: tip 50000 / 4
            if (sub2 == "/" && parts.Length >= 3 && TryParseAmount(parts[2], out var people2))
            {
                items.AddRange(BuildSplitItems(amount, 0, (int)people2));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }

            // 팁%: tip 50000 15  또는  tip 50000 15 4
            if (TryParseAmount(parts[1], out var tipRate))
            {
                var people = parts.Length >= 3 && TryParseAmount(parts[2], out var p) ? (int)p : 1;
                items.AddRange(BuildTipItems(amount, (double)tipRate, people));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }
        }

        // 기본: 팁 퍼센트별 목록
        items.AddRange(BuildDefaultTipItems(amount));
        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("Tip", "클립보드에 복사했습니다.");
            }
            catch { /* 비핵심 */ }
        }
        return Task.CompletedTask;
    }

    // ── 계산 빌더 ─────────────────────────────────────────────────────────────

    private static IEnumerable<LauncherItem> BuildDefaultTipItems(decimal amount)
    {
        yield return new LauncherItem(
            $"원금  {FormatKrw(amount)}",
            "팁 퍼센트별 합계",
            null, ("copy", FormatKrw(amount)), Symbol: "\uE8F0");

        foreach (var rate in DefaultTipRates)
        {
            var tip   = amount * rate / 100;
            var total = amount + tip;
            yield return new LauncherItem(
                $"{rate}%  →  {FormatKrw(total)}",
                $"팁 {FormatKrw(tip)}  ·  합계 {FormatKrw(total)}",
                null, ("copy", FormatKrw(total)), Symbol: "\uE8F0");
        }

        // 분할 미리보기
        yield return new LauncherItem($"2명 분할", FormatKrw(amount / 2), null, ("copy", FormatKrw(amount / 2)), Symbol: "\uE8F0");
        yield return new LauncherItem($"4명 분할", FormatKrw(amount / 4), null, ("copy", FormatKrw(amount / 4)), Symbol: "\uE8F0");
    }

    private static IEnumerable<LauncherItem> BuildTipItems(decimal amount, double tipPct, int people)
    {
        var tip      = amount * (decimal)tipPct / 100;
        var total    = amount + tip;
        var perPerson = people > 1 ? total / people : total;

        yield return new LauncherItem(
            $"합계  {FormatKrw(total)}",
            $"원금 {FormatKrw(amount)}  +  팁 {tipPct}% ({FormatKrw(tip)})",
            null, ("copy", FormatKrw(total)), Symbol: "\uE8F0");

        yield return new LauncherItem("원금",       FormatKrw(amount),    null, ("copy", FormatKrw(amount)),    Symbol: "\uE8F0");
        yield return new LauncherItem($"팁 {tipPct}%", FormatKrw(tip),    null, ("copy", FormatKrw(tip)),       Symbol: "\uE8F0");
        yield return new LauncherItem("합계",       FormatKrw(total),     null, ("copy", FormatKrw(total)),     Symbol: "\uE8F0");

        if (people > 1)
        {
            yield return new LauncherItem(
                $"{people}명 분할",
                $"1인당 {FormatKrw(perPerson)}",
                null, ("copy", FormatKrw(perPerson)), Symbol: "\uE8F0");
        }
    }

    private static IEnumerable<LauncherItem> BuildDiscountItems(decimal amount, double discountPct)
    {
        var discount    = amount * (decimal)discountPct / 100;
        var discounted  = amount - discount;

        yield return new LauncherItem(
            $"할인가  {FormatKrw(discounted)}",
            $"{discountPct}% 할인  (할인액 {FormatKrw(discount)})",
            null, ("copy", FormatKrw(discounted)), Symbol: "\uE8F0");

        yield return new LauncherItem("원가",       FormatKrw(amount),     null, ("copy", FormatKrw(amount)),     Symbol: "\uE8F0");
        yield return new LauncherItem($"할인 {discountPct}%", FormatKrw(discount), null, ("copy", FormatKrw(discount)), Symbol: "\uE8F0");
        yield return new LauncherItem("할인가",     FormatKrw(discounted), null, ("copy", FormatKrw(discounted)), Symbol: "\uE8F0");

        // 다른 할인율 비교
        yield return new LauncherItem("── 할인율 비교 ──", "", null, null, Symbol: "\uE8F0");
        foreach (var rate in DefaultDiscountRates.Where(r => r != (int)discountPct))
        {
            var d = amount * rate / 100;
            yield return new LauncherItem($"{rate}%  →  {FormatKrw(amount - d)}",
                $"할인 {FormatKrw(d)}", null, ("copy", FormatKrw(amount - d)), Symbol: "\uE8F0");
        }
    }

    private static IEnumerable<LauncherItem> BuildVatItems(decimal amount, double vatRate)
    {
        var vat      = amount * (decimal)vatRate / 100;
        var withVat  = amount + vat;
        var exVat    = amount / (1 + (decimal)vatRate / 100);
        var vatOnly  = amount - exVat;

        yield return new LauncherItem(
            $"VAT 포함  {FormatKrw(withVat)}",
            $"VAT {vatRate}%  ({FormatKrw(vat)})",
            null, ("copy", FormatKrw(withVat)), Symbol: "\uE8F0");

        yield return new LauncherItem($"입력액 (VAT 별도)", FormatKrw(amount),  null, ("copy", FormatKrw(amount)), Symbol: "\uE8F0");
        yield return new LauncherItem($"VAT {vatRate}%",   FormatKrw(vat),    null, ("copy", FormatKrw(vat)),    Symbol: "\uE8F0");
        yield return new LauncherItem("VAT 포함 합계",     FormatKrw(withVat), null, ("copy", FormatKrw(withVat)), Symbol: "\uE8F0");
        yield return new LauncherItem("── 역산 (VAT 포함가 입력 시) ──", "", null, null, Symbol: "\uE8F0");
        yield return new LauncherItem("공급가액 (VAT 제외)", $"{FormatKrw(exVat)}", null, ("copy", FormatKrw(exVat)), Symbol: "\uE8F0");
        yield return new LauncherItem("VAT 금액",           $"{FormatKrw(vatOnly)}", null, ("copy", FormatKrw(vatOnly)), Symbol: "\uE8F0");
    }

    private static IEnumerable<LauncherItem> BuildSplitItems(decimal amount, double tipPct, int people)
    {
        if (people <= 0) people = 1;
        var tip      = tipPct > 0 ? amount * (decimal)tipPct / 100 : 0;
        var total    = amount + tip;
        var perPerson = total / people;
        var rounded  = Math.Ceiling(perPerson / 100) * 100; // 100원 단위 올림

        yield return new LauncherItem(
            $"{people}명 분할  1인 {FormatKrw(perPerson)}",
            $"합계 {FormatKrw(total)}",
            null, ("copy", FormatKrw(perPerson)), Symbol: "\uE8F0");

        yield return new LauncherItem("합계",           FormatKrw(total),     null, ("copy", FormatKrw(total)),     Symbol: "\uE8F0");
        yield return new LauncherItem($"1인 (정확)",    FormatKrw(perPerson), null, ("copy", FormatKrw(perPerson)), Symbol: "\uE8F0");
        yield return new LauncherItem($"1인 (100원↑)",  FormatKrw(rounded),   null, ("copy", FormatKrw(rounded)),   Symbol: "\uE8F0");
    }

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

    private static bool TryParseAmount(string s, out decimal result)
    {
        result = 0;
        s = s.Replace(",", "").Replace("원", "").Trim();
        return decimal.TryParse(s, System.Globalization.NumberStyles.Any,
            System.Globalization.CultureInfo.InvariantCulture, out result);
    }

    private static string FormatKrw(decimal amount)
    {
        if (amount == Math.Floor(amount))
            return $"{amount:N0}원";
        return $"{amount:N2}원";
    }
}
