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

namespace AxCopilot.Handlers;

/// <summary>
/// L15-3: BMI·건강 계산기 핸들러. "bmi" 프리픽스로 사용합니다.
///
/// 예: bmi 170 65             → 키 170cm / 몸무게 65kg BMI 계산
///     bmi 170 65 30          → 나이 포함 (기초대사량, 목표 칼로리)
///     bmi 170 65 30 m        → 성별 포함 (남: m/male, 여: f/female)
///     bmi ideal 170          → 키 170cm 적정 체중 범위
/// Enter → 결과를 클립보드에 복사.
/// </summary>
public class BmiHandler : IActionHandler
{
    public string? Prefix => "bmi";

    public PluginMetadata Metadata => new(
        "BMI",
        "BMI·건강 계산기 — BMI · 적정 체중 · 기초대사량 · 칼로리",
        "1.0",
        "AX");

    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("BMI·건강 계산기",
                "예: bmi 170 65  /  bmi 170 65 30 m  /  bmi ideal 170",
                null, null, Symbol: "\uE73E"));
            items.Add(new LauncherItem("bmi <키cm> <몸무게kg>",           "BMI 지수 계산",        null, null, Symbol: "\uE73E"));
            items.Add(new LauncherItem("bmi <키> <몸무게> <나이>",         "기초대사량 포함",      null, null, Symbol: "\uE73E"));
            items.Add(new LauncherItem("bmi <키> <몸무게> <나이> m/f",    "성별 포함 (남/여)",    null, null, Symbol: "\uE73E"));
            items.Add(new LauncherItem("bmi ideal <키cm>",                "적정 체중 범위",       null, null, Symbol: "\uE73E"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

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

        // ideal 서브커맨드
        if (parts[0].Equals("ideal", StringComparison.OrdinalIgnoreCase))
        {
            if (parts.Length < 2 || !double.TryParse(parts[1], out var ht) || ht < 100 || ht > 250)
            {
                items.Add(new LauncherItem("키를 입력하세요", "예: bmi ideal 170", null, null, Symbol: "\uE783"));
                return Task.FromResult<IEnumerable<LauncherItem>>(items);
            }
            items.AddRange(BuildIdealItems(ht));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 키 파싱
        if (!double.TryParse(parts[0].Replace("cm", ""), out var height) || height < 100 || height > 250)
        {
            items.Add(new LauncherItem("키 형식 오류",
                "키를 cm 단위로 입력하세요 (예: 170)", null, null, Symbol: "\uE783"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 몸무게 파싱
        if (parts.Length < 2 || !double.TryParse(parts[1].Replace("kg", ""), out var weight) || weight < 20 || weight > 300)
        {
            items.Add(new LauncherItem("몸무게를 입력하세요",
                $"키 {height}cm → 예: bmi {height} 65", null, null, Symbol: "\uE783"));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // 나이, 성별 (선택)
        int? age  = null;
        bool? male = null;

        for (var i = 2; i < parts.Length; i++)
        {
            var p = parts[i].ToLowerInvariant();
            if (p is "m" or "male" or "남" or "남자" or "남성") { male = true; continue; }
            if (p is "f" or "female" or "여" or "여자" or "여성") { male = false; continue; }
            if (int.TryParse(p, out var a) && a is >= 1 and <= 120) { age = a; continue; }
        }

        items.AddRange(BuildBmiItems(height, weight, age, male));
        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("BMI", "클립보드에 복사했습니다.");
            }
            catch { /* 비핵심 */ }
        }
        return Task.CompletedTask;
    }

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

    private static IEnumerable<LauncherItem> BuildBmiItems(double height, double weight, int? age, bool? male)
    {
        var hm  = height / 100.0;
        var bmi = weight / (hm * hm);
        var (grade, gradeEmoji) = GetGrade(bmi);

        var summary = $"BMI {bmi:F1}  ({grade})";
        yield return new LauncherItem(summary,
            $"키 {height}cm  ·  몸무게 {weight}kg",
            null, ("copy", summary), Symbol: "\uE73E");

        yield return new LauncherItem($"BMI 지수",     $"{bmi:F2}  {gradeEmoji}", null, ("copy", $"{bmi:F2}"), Symbol: "\uE73E");
        yield return new LauncherItem("판정",           grade,                    null, ("copy", grade),        Symbol: "\uE73E");

        // 적정 체중 (BMI 18.5 ~ 22.9 범위)
        var idealMin = 18.5 * hm * hm;
        var idealMax = 22.9 * hm * hm;
        var idealStr = $"{idealMin:F1}kg ~ {idealMax:F1}kg";
        yield return new LauncherItem("적정 체중 범위", idealStr, null, ("copy", idealStr), Symbol: "\uE73E");

        var diff = weight - (idealMin + idealMax) / 2;
        if (Math.Abs(diff) > 0.5)
        {
            var diffStr = diff > 0 ? $"+{diff:F1}kg 과잉" : $"{diff:F1}kg 부족";
            yield return new LauncherItem("표준 체중 대비", diffStr, null, ("copy", diffStr), Symbol: "\uE73E");
        }

        // BMI 등급 기준
        yield return new LauncherItem("── BMI 기준 (WHO 아시아태평양) ──", "", null, null, Symbol: "\uE73E");
        yield return new LauncherItem("저체중",   "BMI < 18.5",       null, null, Symbol: "\uE73E");
        yield return new LauncherItem("정상",     "18.5 ≤ BMI < 23",  null, null, Symbol: "\uE73E");
        yield return new LauncherItem("과체중",   "23 ≤ BMI < 25",    null, null, Symbol: "\uE73E");
        yield return new LauncherItem("비만 1단계","25 ≤ BMI < 30",   null, null, Symbol: "\uE73E");
        yield return new LauncherItem("비만 2단계","BMI ≥ 30",        null, null, Symbol: "\uE73E");

        // 기초대사량 (Harris-Benedict 개정식)
        if (age.HasValue)
        {
            double bmr;
            string bmrLabel;
            if (male == true)
            {
                bmr = 88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age.Value);
                bmrLabel = "남성 기초대사량 (Harris-Benedict)";
            }
            else if (male == false)
            {
                bmr = 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age.Value);
                bmrLabel = "여성 기초대사량 (Harris-Benedict)";
            }
            else
            {
                bmr = (88.362 + (13.397 * weight) + (4.799 * height) - (5.677 * age.Value)
                     + 447.593 + (9.247 * weight) + (3.098 * height) - (4.330 * age.Value)) / 2;
                bmrLabel = "기초대사량 (남녀 평균)";
            }

            var bmrStr = $"{bmr:N0} kcal/일";
            yield return new LauncherItem("── 대사량 ──", "", null, null, Symbol: "\uE73E");
            yield return new LauncherItem(bmrLabel, bmrStr, null, ("copy", bmrStr), Symbol: "\uE73E");

            // 활동 단계별 권장 칼로리
            var actLevels = new[]
            {
                ("비활동 (거의 운동 없음)",  1.2),
                ("저활동 (주 1~3회 운동)",  1.375),
                ("보통 활동 (주 3~5회)",    1.55),
                ("활동적 (주 6~7회)",       1.725),
                ("매우 활동적 (하루 2회)", 1.9),
            };
            foreach (var (label, factor) in actLevels)
            {
                var cal = bmr * factor;
                yield return new LauncherItem(label, $"{cal:N0} kcal/일",
                    null, ("copy", $"{cal:N0} kcal"), Symbol: "\uE73E");
            }
        }
    }

    private static IEnumerable<LauncherItem> BuildIdealItems(double height)
    {
        var hm = height / 100.0;
        var idealMin = 18.5 * hm * hm;
        var idealMax = 22.9 * hm * hm;
        var idealMid = (idealMin + idealMax) / 2;

        yield return new LauncherItem(
            $"키 {height}cm 적정 체중",
            $"{idealMin:F1}kg ~ {idealMax:F1}kg",
            null, ("copy", $"{idealMin:F1}kg ~ {idealMax:F1}kg"), Symbol: "\uE73E");

        yield return new LauncherItem("최소 정상 체중 (BMI 18.5)", $"{idealMin:F1}kg", null, ("copy", $"{idealMin:F1}"), Symbol: "\uE73E");
        yield return new LauncherItem("표준 체중 (BMI 20.7)",      $"{idealMid:F1}kg", null, ("copy", $"{idealMid:F1}"), Symbol: "\uE73E");
        yield return new LauncherItem("최대 정상 체중 (BMI 22.9)", $"{idealMax:F1}kg", null, ("copy", $"{idealMax:F1}"), Symbol: "\uE73E");

        var overMin  = 23.0 * hm * hm;
        var overMax  = 24.9 * hm * hm;
        var obese    = 25.0 * hm * hm;
        yield return new LauncherItem("과체중 범위 (BMI 23~24.9)", $"{overMin:F1}kg ~ {overMax:F1}kg", null, null, Symbol: "\uE73E");
        yield return new LauncherItem("비만 기준 (BMI ≥ 25)",      $"{obese:F1}kg 이상",              null, null, Symbol: "\uE73E");
    }

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

    private static (string Grade, string Emoji) GetGrade(double bmi) => bmi switch
    {
        < 18.5 => ("저체중", "🔵"),
        < 23.0 => ("정상",   "🟢"),
        < 25.0 => ("과체중", "🟡"),
        < 30.0 => ("비만 1단계", "🟠"),
        _      => ("비만 2단계", "🔴"),
    };
}
