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

namespace AsbCloudWebApi.IntegrationTests.Controllers;

public class SlipsStatControllerTest : BaseIntegrationTest
{
	private readonly ISlipsTimeClient client;

	public SlipsStatControllerTest(WebAppFactoryFixture factory)
		: base(factory)
	{
		client = factory.GetAuthorizedHttpClient<ISlipsTimeClient>(string.Empty);

		dbContext.CleanupDbSet<Schedule>();
		dbContext.CleanupDbSet<WellOperation>();
		dbContext.CleanupDbSet<DetectedOperation>();
	}

	[Fact]
	public async Task GetAll_returns_success()
	{
		//arrange
		var well = dbContext.Wells.First();
		var schedule = CreateScheduleAsync(well.Id);
		var factWellOperation = CreateFactWellOperation(well.Id);
		var detectedOperation = CreateDetectedOperation(well.IdTelemetry!.Value);

		dbContext.Schedule.Add(schedule);
		dbContext.WellOperations.Add(factWellOperation);
		dbContext.DetectedOperations.Add(detectedOperation);
		await dbContext.SaveChangesAsync();

		var request = new OperationStatRequest
		{
			DateStartUTC = schedule.DrillStart.DateTime,
			DateEndUTC = schedule.DrillEnd.DateTime,
			DurationMinutesMin = 0,
			DurationMinutesMax = 5
		};

		var dtoExpected = new SlipsStatDto
		{
			DrillerName = $"{schedule.Driller.Surname} {schedule.Driller.Name} {schedule.Driller.Patronymic}",
			WellCount = 1,
			SectionCaption = "Пилотный ствол",
			SlipsCount = 1,
			SlipsTimeInMinutes = (detectedOperation.DateEnd - detectedOperation.DateStart).TotalMinutes,
			SectionDepth = factWellOperation.DepthEnd - factWellOperation.DepthStart,
		};

		//act
		var response = await client.GetAll(request);

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

		var slipsStat = response.Content.First();
		MatchHelper.Match(dtoExpected, slipsStat);
	}

	private static Schedule CreateScheduleAsync(int idWell) => new()
	{
		IdWell = idWell,
		ShiftStart = new TimeOnly(8, 0, 0),
		ShiftEnd = new TimeOnly(20, 0, 0),
		DrillStart = new DateTimeOffset(new DateTime(2024, 1, 1, 0, 0, 0, DateTimeKind.Utc)),
		DrillEnd = new DateTimeOffset(new DateTime(2024, 2, 1, 0, 0, 0, DateTimeKind.Utc)),
		Driller = new Driller
		{
			Name = "TestName",
			Surname = "TestSurname",
			Patronymic = "TestPatronymic"
		}
	};

	private static WellOperation CreateFactWellOperation(int idWell) =>
		new()
		{
			IdWell = idWell,
			IdWellSectionType = 1,
			IdCategory = WellOperationCategory.IdRotor,
			IdType = WellOperation.IdOperationTypeFact,
			DepthStart = 0,
			DepthEnd = 100,
			LastUpdateDate = DateTimeOffset.UtcNow,
			DateStart = new DateTimeOffset(new DateTime(2024, 1, 15, 15, 0, 0, DateTimeKind.Utc)),
			DurationHours = 1
		};

	private static DetectedOperation CreateDetectedOperation(int idTelemetry) =>
		new()
		{
			IdTelemetry = idTelemetry,
			IdCategory = WellOperationCategory.IdSlipsTime,
			DateStart = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 0, 0, 0, DateTimeKind.Utc)),
			DateEnd = new DateTimeOffset(new DateTime(2024, 1, 23, 15, 2, 0, 0, DateTimeKind.Utc)),
			ExtraData = new Dictionary<string, object>
			{
				{ "test", 5 }
			}
		};
}