using System;
using System.Collections.Generic;
using Tornado3_2026Election.Common;
using Tornado3_2026Election.Domain;

namespace Tornado3_2026Election.ViewModels;

public sealed class CareerPromiseEditRowViewModel : ObservableObject
{
    private string _districtName;
    private string _candidateCode;
    private string _candidateName;
    private string _party;
    private string _promise1;
    private string _promise2;
    private string _promise3;

    public CareerPromiseEditRowViewModel(
        string candidateCode,
        string candidateName,
        string party,
        IReadOnlyList<string>? promises = null,
        string districtName = "",
        Action<CareerPromiseEditRowViewModel>? deleteAction = null)
    {
        _candidateCode = candidateCode ?? string.Empty;
        _candidateName = candidateName ?? string.Empty;
        _party = party ?? string.Empty;
        _districtName = districtName ?? string.Empty;
        _promise1 = GetPromise(promises, 0);
        _promise2 = GetPromise(promises, 1);
        _promise3 = GetPromise(promises, 2);
        DeleteCommand = new RelayCommand(() => deleteAction?.Invoke(this), () => deleteAction is not null);
    }

    public RelayCommand DeleteCommand { get; }

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

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

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

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

    public string Promise1
    {
        get => _promise1;
        set
        {
            if (SetProperty(ref _promise1, value ?? string.Empty))
            {
                OnPropertyChanged(nameof(HasAnyPromise));
            }
        }
    }

    public string Promise2
    {
        get => _promise2;
        set
        {
            if (SetProperty(ref _promise2, value ?? string.Empty))
            {
                OnPropertyChanged(nameof(HasAnyPromise));
            }
        }
    }

    public string Promise3
    {
        get => _promise3;
        set
        {
            if (SetProperty(ref _promise3, value ?? string.Empty))
            {
                OnPropertyChanged(nameof(HasAnyPromise));
            }
        }
    }

    public bool HasAnyPromise =>
        !string.IsNullOrWhiteSpace(Promise1) ||
        !string.IsNullOrWhiteSpace(Promise2) ||
        !string.IsNullOrWhiteSpace(Promise3);

    public IReadOnlyList<string> Promises => new[] { Promise1, Promise2, Promise3 };

    public CareerPromiseEntry? ToEntry(
        string stationId,
        string electionType,
        string districtCode,
        string districtName)
    {
        var normalizedCandidateCode = CandidateCode.Trim();
        var normalizedCandidateName = CandidateName.Trim();
        var normalizedParty = Party.Trim();
        if (!HasAnyPromise ||
            string.IsNullOrWhiteSpace(normalizedCandidateName) ||
            string.IsNullOrWhiteSpace(normalizedParty))
        {
            return null;
        }

        var normalizedDistrictName = string.IsNullOrWhiteSpace(DistrictName)
            ? districtName?.Trim() ?? string.Empty
            : DistrictName.Trim();

        return new CareerPromiseEntry
        {
            StationId = stationId?.Trim() ?? string.Empty,
            ElectionType = electionType?.Trim() ?? string.Empty,
            DistrictCode = districtCode?.Trim() ?? string.Empty,
            DistrictName = normalizedDistrictName,
            CandidateCode = normalizedCandidateCode,
            CandidateName = normalizedCandidateName,
            Party = normalizedParty,
            Promises = new[] { Promise1.Trim(), Promise2.Trim(), Promise3.Trim() }
        };
    }

    private static string GetPromise(IReadOnlyList<string>? promises, int index)
    {
        return promises is not null && index >= 0 && index < promises.Count
            ? promises[index] ?? string.Empty
            : string.Empty;
    }
}
