using LiteCqrs;
using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Broadcast.Bumpers;
using TeleWave.Application.Common.Interfaces;
using TeleWave.Application.Common.Models;
using TeleWave.Domain.Programming;

namespace TeleWave.Application.Programming.Templates.Junctions;

public sealed class UpdateJunctionElementCommandHandler(IAppDbContext dbContext)
    : ICommandHandler<UpdateJunctionElementCommand, Result>
{
    public async Task<Result> Handle(
        UpdateJunctionElementCommand command,
        CancellationToken cancellationToken
    )
    {
        var junction = await JunctionLoader.LoadAsync(
            dbContext,
            command.JunctionId,
            cancellationToken
        );
        var element = junction?.FindElement(command.ElementId);
        if (junction is null || element is null)
            return Result.Failure(TemplateErrors.JunctionElementNotFound);

        var input = command.Input;
        var check = await ValidateSourceAsync(input, cancellationToken);
        if (!check.IsSuccess)
            return check;

        element.Update(
            new JunctionElementSettings(
                input.Kind,
                input.GroupId,
                input.BumperTemplateId,
                input.BumperVariantId,
                input.AmountMode,
                input.AmountValue,
                input.IsRequired,
                input.ChoiceKey,
                input.ChoiceWeight,
                input.Conditions?.ToJson()
            )
        );

        return await JunctionLoader.MarkTemplatesChangedAsync(
            dbContext,
            junction.Id,
            cancellationToken
        );
    }

    /// <summary>Источник врезки должен существовать: молча пустая врезка выглядит как «стык не работает».</summary>
    private async Task<Result> ValidateSourceAsync(
        JunctionElementInput input,
        CancellationToken cancellationToken
    )
    {
        if (input.Kind != JunctionElementKind.Bumper)
        {
            if (input.GroupId is not { } groupId)
                return Result.Failure(TemplateErrors.JunctionGroupRequired);
            return await dbContext.Groups.AnyAsync(g => g.Id == groupId, cancellationToken)
                ? Result.Success()
                : Result.Failure(TemplateErrors.GroupNotFound);
        }

        if (input.BumperTemplateId is not { } templateId)
            return Result.Failure(BumperErrors.TemplateNotFound);
        if (!await dbContext.BumperTemplates.AnyAsync(t => t.Id == templateId, cancellationToken))
            return Result.Failure(BumperErrors.TemplateNotFound);

        if (input.BumperVariantId is not { } variantId)
            return Result.Success();

        return await dbContext.BumperTextVariants.AnyAsync(
            v => v.Id == variantId && v.BumperTemplateId == templateId,
            cancellationToken
        )
            ? Result.Success()
            : Result.Failure(BumperErrors.VariantNotFound);
    }
}
