using FluentAssertions;
using Knot.Modules.Stories.Application.Stories.Commands.CreateStory;
using Knot.Modules.Stories.Domain;
using Knot.Shared.Kernel;
using Knot.Modules.Settings.Application.Settings.Abstractions;
using Knot.Modules.Settings.Application.Settings.DTOs;
using Knot.Modules.Stories.Application.Abstractions;
using NSubstitute;
using Xunit;
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Knot.Modules.Stories.UnitTests;

public class CreateStoryCommandHandlerTests
{
    private readonly IStoryRepository _storyRepository;
    private readonly ISettingsService _settingsService;
    private readonly CreateStoryCommandHandler _handler;

    public CreateStoryCommandHandlerTests()
    {
        _storyRepository = Substitute.For<IStoryRepository>();
        _settingsService = Substitute.For<ISettingsService>();
        _handler = new CreateStoryCommandHandler(_storyRepository, _settingsService);
    }

    [Fact]
    public async Task Handle_ShouldSucceed_WhenValidRequest()
    {
        // Arrange
        var command = new CreateStoryCommand(Guid.NewGuid(), "Text", null, "Hello Story", null);

        // Act
        var result = await _handler.Handle(command, CancellationToken.None);

        // Assert
        result.IsSuccess.Should().BeTrue();
        await _storyRepository.Received(1).AddAsync(Arg.Any<Story>(), Arg.Any<CancellationToken>());
    }

    [Fact]
    public async Task Handle_ShouldFail_WhenKlipyDisabledAndKlipyType()
    {
        // Arrange
        var command = new CreateStoryCommand(Guid.NewGuid(), "Klipy", "http://klipy.com/gif", null, null);
        var settings = new SystemSettingsDto { Klipy = new KlipyConfig { Enabled = false } };
        _settingsService.GetSettingsAsync(Arg.Any<CancellationToken>()).Returns(settings);

        // Act
        var result = await _handler.Handle(command, CancellationToken.None);

        // Assert
        result.IsFailure.Should().BeTrue();
        result.Error.Code.Should().Be("Stories.KlipyDisabled");
        await _storyRepository.DidNotReceive().AddAsync(Arg.Any<Story>(), Arg.Any<CancellationToken>());
    }

    [Fact]
    public async Task Handle_ShouldSucceed_WhenKlipyEnabledAndKlipyType()
    {
        // Arrange
        var command = new CreateStoryCommand(Guid.NewGuid(), "Klipy", "http://klipy.com/gif", null, null);
        var settings = new SystemSettingsDto { Klipy = new KlipyConfig { Enabled = true } };
        _settingsService.GetSettingsAsync(Arg.Any<CancellationToken>()).Returns(settings);

        // Act
        var result = await _handler.Handle(command, CancellationToken.None);

        // Assert
        result.IsSuccess.Should().BeTrue();
        await _storyRepository.Received(1).AddAsync(Arg.Any<Story>(), Arg.Any<CancellationToken>());
    }
}

