using AsbCloudApp.Data;
using AsbCloudDb.Model;
using AsbCloudWebApi.IntegrationTests.Clients;
using System.Net;
using AsbCloudApp.Requests;
using Xunit;

namespace AsbCloudWebApi.IntegrationTests.Controllers;

public class WellOperationControllerTest : BaseIntegrationTest
{
    private static int idWell = 1;

	private readonly WellOperationDto[] dtos = new WellOperationDto[]
	{
		new()
		{
			IdWell = 1,
			IdWellSectionType = 1,
			WellSectionTypeName = "Пилотный ствол",
			IdCategory = 5000,
			IdPlan = null,
			CategoryName = "Разборка КНБК",
			IdParentCategory = 4000,
			CategoryInfo = "1",
			IdType = 0,
			DepthStart = 10.0,
			DepthEnd = 20.0,
			Day = 0.0,
			NptHours = 0.0,
			DateStart = new DateTimeOffset(new DateTime(2023, 02, 03, 1, 0, 0, DateTimeKind.Unspecified)),
			DurationHours = 1.0,
			Comment = "1",
			IdUser = 1,
			UserName = null,
		}
	};

    private readonly WellOperationDto[] dtosWithError = new WellOperationDto[]
    {
        new()
        {
            Id = 3,
            IdWell = idWell,
            IdType = 1,
            DateStart = DateTimeOffset.Now,
            CategoryInfo = "1",
            CategoryName = "1",
            Comment = "1",
            Day = 1,
            DepthEnd = 20,
            DepthStart = 10,
            DurationHours = 1,
            IdCategory = 5000,
            IdParentCategory = null,
            IdPlan = null,
            IdUser = 1,
            IdWellSectionType = 1,
            LastUpdateDate = DateTimeOffset.Now,
            NptHours = 1,
            WellSectionTypeName = null,
            UserName = null
        },
        new()
        {
            Id = 4,
            IdWell = idWell,
            IdType = 1,
            DateStart = DateTimeOffset.Now.AddDays(1000),
            CategoryInfo = "1",
            CategoryName = "1",
            Comment = "1",
            Day = 1,
            DepthEnd = 20,
            DepthStart = 10,
            DurationHours = 1,
            IdCategory = 5000,
            IdParentCategory = null,
            IdPlan = null,
            IdUser = 1,
            IdWellSectionType = 1,
            LastUpdateDate = DateTimeOffset.Now,
            NptHours = 1,
            WellSectionTypeName = null,
            UserName = null
        }
    };

	private IWellOperationClient client;

    public WellOperationControllerTest(WebAppFactoryFixture factory)
        : base(factory)
    {
        client = factory.GetAuthorizedHttpClient<IWellOperationClient>();
    }

    /// <summary>
    /// Успешное добавление операций (без предварительной очистки данных)
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task InsertRange_returns_success()
    {
        dbContext.CleanupDbSet<WellOperation>();
        //act
        var response = await client.InsertRangeAsync(idWell, 1, false, dtos);

        //assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }


    /// <summary>
    /// Неуспешное добавление операций (без предварительной очистки данных)
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task InsertRange_returns_error()
    {
        //act
        var response = await client.InsertRangeAsync(idWell, 1, false, dtosWithError);

        //assert
        Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
    }

    /// <summary>
    /// Успешное добавление операций (с предварительной очисткой данных)
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task InsertRangeWithDeleteBefore_returns_success()
    {
        //act
        var response = await client.InsertRangeAsync(idWell, 1, true, dtos);

        //assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }

    /// <summary>
    /// Неуспешное добавление операций (с предварительной очисткой данных)
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task InsertRangeWithDeleteBefore_returns_error()
    {
        //act
        var response = await client.InsertRangeAsync(idWell, 1, true, dtosWithError);

        //assert
        Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
    }

    /// <summary>
    /// Успешное обновление операции
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task UpdateAsync_returns_success()
    {
        //act
        var dto = dtos.FirstOrDefault()!;
        var response = await client.UpdateAsync(idWell, 1, dto, CancellationToken.None);

        //assert
        Assert.Equal(HttpStatusCode.OK, response.StatusCode);
    }

    /// <summary>
    /// Неуспешное обновление операции
    /// </summary>
    /// <returns></returns>
    [Fact]
    public async Task UpdateAsync_returns_error()
    {
        //act
        var dto = dtosWithError.LastOrDefault()!;
        var response = await client.UpdateAsync(idWell, 1, dto, CancellationToken.None);

        //assert
        Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
    }
	
	/// <summary>
	/// Получение плановых операций
	/// </summary>
	/// <returns></returns>
	[Fact]
	public async Task GetPageOperationsPlanAsync_returns_success()
	{
		//arrange
		dbContext.CleanupDbSet<WellOperation>();
		await client.InsertRangeAsync(idWell, WellOperation.IdOperationTypePlan, false, dtos);

		var request = new WellOperationRequestBase
		{
			OperationType = WellOperation.IdOperationTypePlan
		};

		//act
		var response = await client.GetPageOperationsPlanAsync(idWell, request, CancellationToken.None);

		//assert
		Assert.NotNull(response.Content);
		Assert.Single(response.Content.Items);

		var dto = dtos[0];
		var wellOperation = response.Content.Items.First();

		var excludeProps = new[] { nameof(WellOperationDto.Id) };
		MatchHelper.Match(dto, wellOperation, excludeProps);
	}
}