using System.Collections.Generic;
using System.Linq;
using Microsoft.UI;
using Microsoft.UI.Xaml.Media;
using Tornado3_2026Election.Common;
using Tornado3_2026Election.Domain;

namespace Tornado3_2026Election.ViewModels;

public sealed class PreElectionHistoryWinnerEditRowViewModel : ObservableObject
{
    private static readonly ColorPreviewSpec ConservativePreview = CreatePreviewSpec(181, 25, 36, 227, 46, 68, 245, 187, 191, 119, 20, 28);
    private static readonly ColorPreviewSpec DemocraticPreview = CreatePreviewSpec(0, 69, 143, 0, 91, 187, 171, 205, 246, 13, 46, 92);
    private static readonly ColorPreviewSpec ReformPreview = CreatePreviewSpec(232, 110, 0, 255, 130, 34, 255, 214, 168, 145, 68, 0);
    private static readonly ColorPreviewSpec InnovationPreview = CreatePreviewSpec(2, 33, 117, 14, 58, 166, 165, 188, 247, 7, 26, 75);
    private static readonly ColorPreviewSpec ProgressivePreview = CreatePreviewSpec(179, 0, 33, 215, 0, 52, 247, 181, 197, 111, 0, 20);
    private static readonly ColorPreviewSpec JusticePreview = CreatePreviewSpec(194, 149, 0, 238, 186, 0, 255, 236, 153, 117, 90, 0);
    private static readonly ColorPreviewSpec GreenPreview = CreatePreviewSpec(0, 126, 60, 0, 169, 88, 173, 230, 198, 0, 74, 35);
    private static readonly ColorPreviewSpec OtherPreview = CreatePreviewSpec(94, 103, 115, 134, 144, 156, 214, 219, 226, 61, 69, 77);

    private string _name;
    private string _party;
    private string _colorParty;
    private string _note;
    private ColorPreviewSpec _colorPartyPreview;

    public PreElectionHistoryWinnerEditRowViewModel(
        int electionOrder,
        int year,
        IReadOnlyList<SelectionOption<string>> colorPartyOptions,
        PreElectionHistoricalWinnerEntry? entry = null)
    {
        ElectionOrder = electionOrder;
        Year = year;
        _name = entry?.Name ?? string.Empty;
        _party = entry?.Party ?? string.Empty;
        _colorParty = entry?.ColorParty ?? string.Empty;
        _note = entry?.Note ?? string.Empty;
        _colorPartyPreview = ResolvePreview(_colorParty, _party);

        var options = colorPartyOptions.ToList();
        if (!string.IsNullOrWhiteSpace(_colorParty) &&
            options.All(option => !string.Equals(option.Value, _colorParty, System.StringComparison.Ordinal)))
        {
            options.Add(new SelectionOption<string>(_colorParty, _colorParty));
        }

        ColorPartyOptions = options;
    }

    public int ElectionOrder { get; }

    public int Year { get; }

    public IReadOnlyList<SelectionOption<string>> ColorPartyOptions { get; }

    public string Name
    {
        get => _name;
        set => SetProperty(ref _name, value ?? string.Empty);
    }

    public string Party
    {
        get => _party;
        set
        {
            if (SetProperty(ref _party, value ?? string.Empty))
            {
                RefreshColorPartyPreview();
            }
        }
    }

    public string ColorParty
    {
        get => _colorParty;
        set
        {
            if (SetProperty(ref _colorParty, value ?? string.Empty))
            {
                RefreshColorPartyPreview();
            }
        }
    }

    public string Note
    {
        get => _note;
        set => SetProperty(ref _note, value ?? string.Empty);
    }

    public SolidColorBrush ColorPartyPreviewAccentBrush => _colorPartyPreview.AccentBrush;

    public SolidColorBrush ColorPartyPreviewBaseBrush => _colorPartyPreview.BaseBrush;

    public SolidColorBrush ColorPartyPreviewSecondaryBrush => _colorPartyPreview.SecondaryBrush;

    public SolidColorBrush ColorPartyPreviewOutlineBrush => _colorPartyPreview.OutlineBrush;

    public string ColorPartyPreviewSummary => ResolvePreviewSummary();

    public PreElectionHistoricalWinnerEntry? ToEntry()
    {
        var trimmedName = Name?.Trim() ?? string.Empty;
        if (string.IsNullOrWhiteSpace(trimmedName))
        {
            return null;
        }

        return new PreElectionHistoricalWinnerEntry
        {
            ElectionOrder = ElectionOrder,
            Year = Year,
            Name = trimmedName,
            Party = Party?.Trim() ?? string.Empty,
            ColorParty = ColorParty?.Trim() ?? string.Empty,
            Note = Note?.Trim() ?? string.Empty
        };
    }

    private void RefreshColorPartyPreview()
    {
        _colorPartyPreview = ResolvePreview(_colorParty, _party);
        OnPropertyChanged(
            nameof(ColorPartyPreviewAccentBrush),
            nameof(ColorPartyPreviewBaseBrush),
            nameof(ColorPartyPreviewSecondaryBrush),
            nameof(ColorPartyPreviewOutlineBrush),
            nameof(ColorPartyPreviewSummary));
    }

    private string ResolvePreviewSummary()
    {
        var trimmedColorParty = _colorParty?.Trim() ?? string.Empty;
        if (!string.IsNullOrWhiteSpace(trimmedColorParty))
        {
            return $"선택 적용 · {ResolvePreviewLabel(trimmedColorParty)}";
        }

        var trimmedParty = _party?.Trim() ?? string.Empty;
        return string.IsNullOrWhiteSpace(trimmedParty)
            ? "정당명을 입력하면 색감이 바로 잡힙니다."
            : $"표기 정당 기준 · {trimmedParty}";
    }

    private static ColorPreviewSpec ResolvePreview(string colorParty, string party)
    {
        var selectedParty = string.IsNullOrWhiteSpace(colorParty)
            ? party?.Trim() ?? string.Empty
            : colorParty.Trim();
        var normalizedParty = NormalizePartyKey(selectedParty);
        if (string.IsNullOrWhiteSpace(normalizedParty))
        {
            return OtherPreview;
        }

        if (normalizedParty.Contains("무소속", System.StringComparison.Ordinal) ||
            normalizedParty.Contains("무기타", System.StringComparison.Ordinal) ||
            normalizedParty.Contains("기타", System.StringComparison.Ordinal))
        {
            return OtherPreview;
        }

        if (normalizedParty is "국민의힘" or "국힘" or "미래통합당" or "자유한국당" or "새누리당" or "한나라당" or "신한국당" or "민주자유당")
        {
            return ConservativePreview;
        }

        if (normalizedParty is "더불어민주당" or "민주당" or "민주당1991" or "민주당2000" or "민주당2008" or "새정치국민회의" or "새천년민주당" or "열린민주당" or "열린우리당" or "민주통합당" or "새정치민주연합")
        {
            return DemocraticPreview;
        }

        if (normalizedParty is "개혁신당")
        {
            return ReformPreview;
        }

        if (normalizedParty is "조국혁신당")
        {
            return InnovationPreview;
        }

        if (normalizedParty is "진보당" or "민주노동당" or "통합진보당")
        {
            return ProgressivePreview;
        }

        if (normalizedParty is "정의당")
        {
            return JusticePreview;
        }

        if (normalizedParty is "녹색당")
        {
            return GreenPreview;
        }

        return OtherPreview;
    }

    private static string ResolvePreviewLabel(string colorParty)
    {
        var trimmed = colorParty.Trim();
        if (string.IsNullOrWhiteSpace(trimmed))
        {
            return "표기 그대로";
        }

        return string.Equals(trimmed, "무기타", System.StringComparison.Ordinal)
            ? "무소속/기타"
            : trimmed;
    }

    private static string NormalizePartyKey(string partyName)
    {
        return partyName.Trim().Replace(" ", string.Empty);
    }

    private static ColorPreviewSpec CreatePreviewSpec(
        byte accentR,
        byte accentG,
        byte accentB,
        byte baseR,
        byte baseG,
        byte baseB,
        byte secondaryR,
        byte secondaryG,
        byte secondaryB,
        byte outlineR,
        byte outlineG,
        byte outlineB)
    {
        return new ColorPreviewSpec(
            new SolidColorBrush(ColorHelper.FromArgb(byte.MaxValue, accentR, accentG, accentB)),
            new SolidColorBrush(ColorHelper.FromArgb(byte.MaxValue, baseR, baseG, baseB)),
            new SolidColorBrush(ColorHelper.FromArgb(byte.MaxValue, secondaryR, secondaryG, secondaryB)),
            new SolidColorBrush(ColorHelper.FromArgb(byte.MaxValue, outlineR, outlineG, outlineB)));
    }

    private sealed record ColorPreviewSpec(
        SolidColorBrush AccentBrush,
        SolidColorBrush BaseBrush,
        SolidColorBrush SecondaryBrush,
        SolidColorBrush OutlineBrush);
}
