using LiteCqrs;
using Microsoft.EntityFrameworkCore;
using TeleWave.Application.Broadcast;
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;

        if (input.Kind == JunctionElementKind.Bumper)
        {
            var known = await dbContext
                .Channels.Where(c => c.Id == junction.ChannelId)
                .SelectMany(c => c.BumperTemplates)
                .AnyAsync(t => t.Id == input.BumperTemplateId, cancellationToken);
            if (!known)
                return Result.Failure(ChannelErrors.BumperTemplateNotFound);
        }
        else
        {
            if (input.GroupId is not { } groupId)
                return Result.Failure(TemplateErrors.JunctionGroupRequired);
            if (!await dbContext.Groups.AnyAsync(g => g.Id == groupId, cancellationToken))
                return Result.Failure(TemplateErrors.GroupNotFound);
        }

        element.Update(
            input.Kind,
            input.GroupId,
            input.BumperTemplateId,
            input.AmountMode,
            input.AmountValue,
            input.IsRequired,
            input.Conditions?.ToJson()
        );

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