using System.Text.Json;
using RolemasterDb.App.Features;

namespace RolemasterDb.App.Components.Shared;

public sealed class CriticalCellEditorModel
{
    public int ResultId { get; set; }
    public string TableSlug { get; set; } = string.Empty;
    public string TableName { get; set; } = string.Empty;
    public string SourceDocument { get; set; } = string.Empty;
    public string RollBand { get; set; } = string.Empty;
    public string? GroupKey { get; set; }
    public string? GroupLabel { get; set; }
    public string ColumnKey { get; set; } = string.Empty;
    public string ColumnLabel { get; set; } = string.Empty;
    public string ColumnRole { get; set; } = string.Empty;
    public bool IsCurated { get; set; }
    public int? SourcePageNumber { get; set; }
    public string? SourceImageUrl { get; set; }
    public string RawCellText { get; set; } = string.Empty;
    public string QuickParseInput { get; set; } = string.Empty;
    public string DescriptionText { get; set; } = string.Empty;
    public string? RawAffixText { get; set; }
    public string ParseStatus { get; set; } = string.Empty;
    public string ParsedJson { get; set; } = "{}";
    public bool IsDescriptionOverridden { get; set; }
    public bool IsRawAffixTextOverridden { get; set; }
    public bool AreEffectsOverridden { get; set; }
    public bool AreBranchesOverridden { get; set; }
    public List<string> ValidationMessages { get; set; } = [];
    public List<CriticalEffectEditorModel> Effects { get; set; } = [];
    public List<CriticalBranchEditorModel> Branches { get; set; } = [];
    public CriticalCellComparisonState? GeneratedState { get; set; }

    public static CriticalCellEditorModel FromResponse(CriticalCellEditorResponse response) =>
        new()
        {
            ResultId = response.ResultId,
            TableSlug = response.TableSlug,
            TableName = response.TableName,
            SourceDocument = response.SourceDocument,
            RollBand = response.RollBand,
            GroupKey = response.GroupKey,
            GroupLabel = response.GroupLabel,
            ColumnKey = response.ColumnKey,
            ColumnLabel = response.ColumnLabel,
            ColumnRole = response.ColumnRole,
            IsCurated = response.IsCurated,
            SourcePageNumber = response.SourcePageNumber,
            SourceImageUrl = response.SourceImageUrl,
            RawCellText = response.RawCellText,
            QuickParseInput = response.QuickParseInput,
            DescriptionText = response.DescriptionText,
            RawAffixText = response.RawAffixText,
            ParseStatus = response.ParseStatus,
            ParsedJson = response.ParsedJson,
            IsDescriptionOverridden = response.IsDescriptionOverridden,
            IsRawAffixTextOverridden = response.IsRawAffixTextOverridden,
            AreEffectsOverridden = response.AreEffectsOverridden,
            AreBranchesOverridden = response.AreBranchesOverridden,
            ValidationMessages = response.ValidationMessages.ToList(),
            Effects = response.Effects.Select(CriticalEffectEditorModel.FromItem).ToList(),
            Branches = response.Branches.Select(CriticalBranchEditorModel.FromItem).ToList(),
            GeneratedState = response.GeneratedState
        };

    public CriticalCellUpdateRequest ToRequest()
    {
        var request = new CriticalCellUpdateRequest(
            RawCellText,
            QuickParseInput,
            DescriptionText,
            RawAffixText,
            ResolveParseStatus(Effects, Branches),
            SerializeParsedEffects(Effects),
            IsCurated,
            IsDescriptionOverridden,
            IsRawAffixTextOverridden,
            AreEffectsOverridden,
            AreBranchesOverridden,
            Effects.Select(effect => effect.ToItem()).ToList(),
            Branches
                .OrderBy(branch => branch.SortOrder)
                .Select((branch, index) =>
                {
                    branch.SortOrder = index + 1;
                    return branch.ToItem();
                })
                .ToList());

        return request with
        {
            ParsedJson = CriticalCellEditorSnapshot.FromRequest(request).ToJson()
        };
    }

    public CriticalCellEditorModel Clone() =>
        new()
        {
            ResultId = ResultId,
            TableSlug = TableSlug,
            TableName = TableName,
            SourceDocument = SourceDocument,
            RollBand = RollBand,
            GroupKey = GroupKey,
            GroupLabel = GroupLabel,
            ColumnKey = ColumnKey,
            ColumnLabel = ColumnLabel,
            ColumnRole = ColumnRole,
            IsCurated = IsCurated,
            SourcePageNumber = SourcePageNumber,
            SourceImageUrl = SourceImageUrl,
            RawCellText = RawCellText,
            QuickParseInput = QuickParseInput,
            DescriptionText = DescriptionText,
            RawAffixText = RawAffixText,
            ParseStatus = ParseStatus,
            ParsedJson = ParsedJson,
            IsDescriptionOverridden = IsDescriptionOverridden,
            IsRawAffixTextOverridden = IsRawAffixTextOverridden,
            AreEffectsOverridden = AreEffectsOverridden,
            AreBranchesOverridden = AreBranchesOverridden,
            ValidationMessages = ValidationMessages.ToList(),
            Effects = Effects.Select(effect => effect.Clone()).ToList(),
            Branches = Branches.Select(branch => branch.Clone()).ToList(),
            GeneratedState = GeneratedState
        };

    private static string ResolveParseStatus(
        IReadOnlyList<CriticalEffectEditorModel> effects,
        IReadOnlyList<CriticalBranchEditorModel> branches) =>
        effects.Count > 0 || branches.Any(branch => branch.Effects.Count > 0)
            ? "partial"
            : "raw";

    private static string SerializeParsedEffects(IReadOnlyList<CriticalEffectEditorModel> effects) =>
        effects.Count == 0
            ? "{}"
            : JsonSerializer.Serialize(new { effects = effects.Select(effect => effect.ToItem()).ToList() });
}
