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

namespace AsbCloudWebApi.IntegrationTests.Controllers.ProcessMapPlan;

public class ProcessMapReportDrillingControllerTest : BaseIntegrationTest
{
	private IProcessMapReportDrilling client;

	public ProcessMapReportDrillingControllerTest(WebAppFactoryFixture factory)
		: base(factory)
	{
		dbContext.CleanupDbSet<DataSaubStat>();
		dbContext.CleanupDbSet<ProcessMapPlanDrilling>();
		client = factory.GetAuthorizedHttpClient<IProcessMapReportDrilling>(string.Empty);
	}

	[Fact]
	public async Task Get_rtk_report_by_default_request_returns_success()
	{
		//arrange
		var well = dbContext.Wells.First();

		var processMapPlanDrilling = CreateProcessMapPlanDrilling(well.Id);
		dbContext.ProcessMapPlanDrilling.Add(processMapPlanDrilling);

		var wellOperation = CreateWellOperation(well.Id);
		dbContext.WellOperations.Add(wellOperation);

		var dataSaubStats = CreateDataSaubStats(well.IdTelemetry!.Value, wellOperation.IdCategory);
		dbContext.DataSaubStat.AddRange(dataSaubStats);

		await dbContext.SaveChangesAsync();

		//act
		var request = new DataSaubStatRequest();
		var response = await client.GetReportAsync(well.Id, request, CancellationToken.None);

		//assert
		Assert.Equal(HttpStatusCode.OK, response.StatusCode);
		Assert.NotNull(response.Content);
		Assert.Equal(dataSaubStats.Count() - 1, response.Content.Count());
	}

	[Fact]
	public async Task Get_rtk_report_by_parametrize_request_returns_success()
	{
		//arrange
		var well = dbContext.Wells.First();

		var processMapPlanDrilling = CreateProcessMapPlanDrilling(well.Id);
		dbContext.ProcessMapPlanDrilling.Add(processMapPlanDrilling);

		var wellOperation = CreateWellOperation(well.Id);
		dbContext.WellOperations.Add(wellOperation);

		var dataSaubStats = CreateDataSaubStats(well.IdTelemetry!.Value, wellOperation.IdCategory);
		dbContext.DataSaubStat.AddRange(dataSaubStats);

		await dbContext.SaveChangesAsync();
	
		var request = new DataSaubStatRequest
		{
			DeltaAxialLoad = 5,
			DeltaPressure = 15,
			DeltaRotorTorque = 10
		};
		
		//act
		var response = await client.GetReportAsync(well.Id, request, CancellationToken.None);
	
		//assert
		Assert.Equal(HttpStatusCode.OK, response.StatusCode);
		Assert.NotNull(response.Content);
		Assert.Single(response.Content);
	}
	
	[Fact]
	public async Task Get_rtk_report_returns_BadRequest()
	{
		//act
		var request = new DataSaubStatRequest()
		{
			DeltaAxialLoad = 15,
			DeltaPressure = 25,
			DeltaRotorTorque = 20
		};
		var response = await client.GetReportAsync(0, request, CancellationToken.None);
	
		//assert
		Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);
	}
	
	[Fact]
	public async Task Export_rtk_report_returns_success()
	{ 
		//arrange
		var well = dbContext.Wells.First();

		var processMapPlanDrilling = CreateProcessMapPlanDrilling(well.Id);
		dbContext.ProcessMapPlanDrilling.Add(processMapPlanDrilling);

		var wellOperation = CreateWellOperation(well.Id);
		dbContext.WellOperations.Add(wellOperation);

		var dataSaubStats = CreateDataSaubStats(well.IdTelemetry!.Value, wellOperation.IdCategory);
		dbContext.DataSaubStat.AddRange(dataSaubStats);

		await dbContext.SaveChangesAsync();
		
		//act
		var request = new DataSaubStatRequest();
		var response = await client.ExportReportAsync(1, request, CancellationToken.None);
	
		//assert
		Assert.Equal(HttpStatusCode.OK, response.StatusCode);
		Assert.Equal("application/octet-stream", response.ContentHeaders?.ContentType?.MediaType);
		Assert.True(response.ContentHeaders?.ContentLength > 0);
	}

	private static WellOperation CreateWellOperation(int idWell) =>
		new()
		{
			CategoryInfo = "CategoryInfo",
			Comment = "Comment",
			DateStart = DateTimeOffset.UtcNow,
			DepthEnd = 1,
			DepthStart = 0.6,
			DurationHours = 10,
			IdCategory = WellOperationCategory.IdSlide,
			IdPlan = null,
			IdType = WellOperation.IdOperationTypeFact,
			IdUser = 1,
			IdWell = idWell,
			IdWellSectionType = 1,
			LastUpdateDate = DateTimeOffset.UtcNow
		};

	private static ProcessMapPlanDrilling CreateProcessMapPlanDrilling(int idWell) =>
		new()
		{
			IdAuthor = 1,
			IdEditor = null,
			Creation = DateTimeOffset.UtcNow,
			Obsolete = null,
			IdState = ChangeLogAbstract.IdStateActual,
			IdPrevious = null,

			IdWell = idWell,
			IdWellSectionType = 1,
			DepthStart = 0.5,
			DepthEnd = 1.5,

			IdMode = 1,
			AxialLoadPlan = 2.718281,
			AxialLoadLimitMax = 3.1415926,
			DeltaPressurePlan = 4,
			DeltaPressureLimitMax = 5,
			TopDriveTorquePlan = 6,
			TopDriveTorqueLimitMax = 7,
			TopDriveSpeedPlan = 8,
			TopDriveSpeedLimitMax = 9,
			FlowPlan = 10,
			FlowLimitMax = 11,
			RopPlan = 12,
			UsageSaub = 13,
			UsageSpin = 14,
			Comment = "это тестовая запись",
		};

	private static IEnumerable<DataSaubStat> CreateDataSaubStats(int idTelemetry,
		int idCategory) =>
		new[]
		{
			new DataSaubStat
			{
				AxialLoad = 0,
				AxialLoadLimitMax = 10,
				AxialLoadSp = 8,
				BlockSpeedSp = 50.0,
				DateEnd = DateTimeOffset.UtcNow.AddMinutes(40),
				DateStart = DateTimeOffset.UtcNow.AddMinutes(30),
				DepthEnd = 85.99299621582031,
				DepthStart = 85.9260025024414,
				EnabledSubsystems = 0,
				Flow = 10,
				IdCategory = idCategory,
				HasOscillation = true,
				IdFeedRegulator = 0,
				IdTelemetry = idTelemetry,
				Pressure = 24,
				PressureIdle = 0,
				PressureSp = 40,
				RotorSpeed = 11.3,
				RotorTorque = 1,
				RotorTorqueLimitMax = 26.5,
				RotorTorqueSp = 5,
				Speed = 80.3924560546875
			},
			new DataSaubStat
			{
				AxialLoad = 2,
				AxialLoadLimitMax = 10.0,
				AxialLoadSp = 8,
				BlockSpeedSp = 20,
				DateEnd = DateTimeOffset.UtcNow.AddMinutes(30),
				DateStart = DateTimeOffset.UtcNow.AddMinutes(20),
				DepthEnd = 86.28099822998047,
				DepthStart = 86.21900177001953,
				EnabledSubsystems = 1,
				Flow = 20,
				HasOscillation = true,
				IdCategory = idCategory,
				IdFeedRegulator = 1,
				IdTelemetry = idTelemetry,
				Pressure = 30,
				PressureIdle = 20,
				PressureSp = 40,
				RotorSpeed = 11.251153300212916,
				RotorTorque = 7,
				RotorTorqueLimitMax = 26.5,
				RotorTorqueSp = 9,
				Speed = 74.395751953125
			},
			new DataSaubStat
			{
				AxialLoad = 4,
				AxialLoadLimitMax = 15.0,
				AxialLoadSp = 8,
				BlockSpeedSp = 110.0,
				DateEnd = DateTimeOffset.UtcNow.AddMinutes(20),
				DateStart = DateTimeOffset.UtcNow.AddMinutes(10),
				DepthEnd = 106.7490005493164,
				DepthStart = 106.47899627685547,
				EnabledSubsystems = 1,
				Flow = 30,
				HasOscillation = true,
				IdFeedRegulator = 1,
				IdTelemetry = idTelemetry,
				IdCategory = idCategory,
				Pressure = 36,
				PressureIdle = 23.0,
				PressureSp = 63.0,
				RotorSpeed = 11.334207942999628,
				RotorTorque = 14,
				RotorTorqueLimitMax = 15.0,
				RotorTorqueSp = 13,
				Speed = 108.001708984375
			}
		};
}