using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.ProcessMaps;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using AsbCloudInfrastructure.Repository;
using AsbCloudInfrastructure.Services.ProcessMaps;
using AsbCloudInfrastructure.Services.ProcessMaps.Report;
using DocumentFormat.OpenXml.Bibliography;
using DocumentFormat.OpenXml.Spreadsheet;
using NSubstitute;
using Xunit;

namespace AsbCloudWebApi.Tests.Services.ProcessMaps;

public class ProcessMapReportDataSaubStatServiceTest
{


    private IWellService wellService 
        = Substitute.For<IWellService>();

    private IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell> processMapPlanBaseRepository 
        = Substitute.For<IChangeLogRepository<ProcessMapPlanDrillingDto, ProcessMapPlanBaseRequestWithWell>>();

    private IWellOperationRepository wellOperationRepository 
        = Substitute.For<IWellOperationRepository>();

    private IWellOperationCategoryRepository wellOperationCategoryRepository 
        = Substitute.For<IWellOperationCategoryRepository>();

    private IDataSaubStatRepository dataSaubStatRepository 
        = Substitute.For<IDataSaubStatRepository>();

    private ProcessMapReportDrillingService service;

    private readonly static SimpleTimezoneDto timezone = new() { Hours = 2 };
    private static readonly DateTimeOffset dateStart = new (2024, 01, 01, 00, 11, 11, timezone.Offset);
    private readonly static WellDto well = new() 
    { 
        Id = 1,
        IdTelemetry = 1,
        Timezone = timezone
    };
    private readonly static IEnumerable<ProcessMapPlanDrillingDto> processMapPlan = new List<ProcessMapPlanDrillingDto>()
    {
        new() {
            DepthStart = 0, 
            DepthEnd = 100,
            IdMode = 1,
            IdWell = well.Id,
            IdWellSectionType = 1,
            AxialLoadPlan = 0.2,
            AxialLoadLimitMax = 0.3,
            DeltaPressurePlan = 0.4,
            DeltaPressureLimitMax = 0.5,
            TopDriveTorquePlan = 0.6,
            TopDriveTorqueLimitMax = 0.7,
            TopDriveSpeedPlan = 0.8,
            TopDriveSpeedLimitMax = 0.9,
            FlowPlan = 0.10,
            FlowLimitMax = 0.11,
            RopPlan = 0.12,
            UsageSaub = 0.12,
            UsageSpin = 0.14,
            Comment = "r",
        },
        new() {
            DepthStart = 0,
            DepthEnd = 100,
            IdMode = 2,
            IdWell = well.Id,
            IdWellSectionType = 1,
            AxialLoadPlan = 0.12,
            AxialLoadLimitMax = 0.13,
            DeltaPressurePlan = 0.14,
            DeltaPressureLimitMax = 0.15,
            TopDriveTorquePlan = 0.16,
            TopDriveTorqueLimitMax = 0.17,
            TopDriveSpeedPlan = 0.18,
            TopDriveSpeedLimitMax = 0.19,
            FlowPlan = 0.110,
            FlowLimitMax = 0.111,
            RopPlan = 0.112,
            UsageSaub = 0.112,
            UsageSpin = 0.114,
            Comment = "s",
        },
        new() {
            DepthStart = 100,
            DepthEnd = 200,
            IdMode = 1,
            IdWell = well.Id,
            IdWellSectionType = 1,
            AxialLoadPlan = 0.22,
            AxialLoadLimitMax = 0.23,
            DeltaPressurePlan = 0.24,
            DeltaPressureLimitMax = 0.25,
            TopDriveTorquePlan = 0.26,
            TopDriveTorqueLimitMax = 0.27,
            TopDriveSpeedPlan = 0.28,
            TopDriveSpeedLimitMax = 0.29,
            FlowPlan = 0.210,
            FlowLimitMax = 0.211,
            RopPlan = 0.212,
            UsageSaub = 0.212,
            UsageSpin = 0.214,
            Comment = "r",
        },
        new() {
            DepthStart = 100,
            DepthEnd = 200,
            IdMode = 2,
            IdWell = well.Id,
            IdWellSectionType = 1,
            AxialLoadPlan = 0.32,
            AxialLoadLimitMax = 0.33,
            DeltaPressurePlan = 0.34,
            DeltaPressureLimitMax = 0.35,
            TopDriveTorquePlan = 0.36,
            TopDriveTorqueLimitMax = 0.37,
            TopDriveSpeedPlan = 0.38,
            TopDriveSpeedLimitMax = 0.39,
            FlowPlan = 0.310,
            FlowLimitMax = 0.311,
            RopPlan = 0.312,
            UsageSaub = 0.312,
            UsageSpin = 0.314,
            Comment = "s",
        },
    };
    private readonly static IEnumerable<WellOperationDto> operations = new List<WellOperationDto>()
    {
        new()
        {
            Id = 1,
            IdWell = well.Id,
            IdWellSectionType = 1,
            IdCategory = WellOperationCategory.IdRotor,
            IdParentCategory = WellOperationCategory.IdMechanicalDrilling,
            IdType = WellOperation.IdOperationTypeFact,
            DepthStart = 0,
            DepthEnd = 10,
            DateStart = dateStart,
            DurationHours = 1,
        },
                new()
        {
            Id = 1,
            IdWell = well.Id,
            IdWellSectionType = 2,
            IdCategory = WellOperationCategory.IdRotor,
            IdParentCategory = WellOperationCategory.IdMechanicalDrilling,
            IdType = WellOperation.IdOperationTypeFact,
            DepthStart = 50,
            DepthEnd = 100,
            DateStart = dateStart,
            DurationHours = 1,
        }
    };
    private readonly static IEnumerable<WellOperationCategoryDto> operationCategories = new List<WellOperationCategoryDto>()
    {
        new(){Id = WellOperationCategory.IdRotor, IdParent = WellOperationCategory.IdMechanicalDrilling, Name = "РОТОР"},
        new(){Id = WellOperationCategory.IdSlide, IdParent = WellOperationCategory.IdMechanicalDrilling, Name = "СЛАЙД"},
    };
    private readonly static IEnumerable<WellSectionTypeDto> sectionTypes = new List<WellSectionTypeDto>() {
        new(){ Id = 1, Caption = "Секция 1"},
        new(){ Id = 2, Caption = "Секция 2"},
        new(){ Id = 3, Caption = "Секция 3"},
        new(){ Id = 4, Caption = "Секция 4"},
    };
    private readonly static IEnumerable<DataSaubStatDto> dataSaubStat = new List<DataSaubStatDto>() {
        new(){
            Id = 1,
            IdTelemetry = 1,
            IdCategory = WellOperationCategory.IdRotor,
            DateStart = dateStart,
            DateEnd = dateStart.AddHours(3.25),
            DepthStart = 0,
            DepthEnd = 20,
            Speed = 0.1,
            BlockSpeedSp = 0.2,
            Pressure = 0.3,
            PressureIdle = 0.4,
            PressureSp = 0.5,
            AxialLoad = 0.6,
            AxialLoadSp = 0.7,
            AxialLoadLimitMax = 0.8,
            RotorTorque = 0.9,
            RotorTorqueSp = 0.11,
            RotorTorqueLimitMax = 0.12,
            RotorSpeed = 0.14,
            Flow = 0.17,
            IdFeedRegulator = LimitingParameterDto.AxialLoad,
            EnabledSubsystems = 15,
            HasOscillation = false,
        },
        new(){
            Id = 1,
            IdTelemetry = 1,
            IdCategory = WellOperationCategory.IdRotor,
            DateStart = dateStart.AddHours(3.25),
            DateEnd = dateStart.AddHours(4.25),
            DepthStart = 20,
            DepthEnd = 190,
            Speed = 0.21,
            BlockSpeedSp = 0.22,
            Pressure = 0.23,
            PressureIdle = 0.24,
            PressureSp = 0.25,
            AxialLoad = 0.26,
            AxialLoadSp = 0.27,
            AxialLoadLimitMax = 0.28,
            RotorTorque = 0.29,
            RotorTorqueSp = 0.211,
            RotorTorqueLimitMax = 0.212,
            RotorSpeed = 0.214,
            Flow = 0.217,
            IdFeedRegulator = LimitingParameterDto.AxialLoad,
            EnabledSubsystems = 15,
            HasOscillation = false,
        },
        new(){
            Id = 1,
            IdTelemetry = 1,
            IdCategory = WellOperationCategory.IdRotor,
            DateStart = dateStart.AddHours(4.25),
            DateEnd = dateStart.AddHours(16),
            DepthStart = 190,
            DepthEnd = 290,
            Speed = 0.31,
            BlockSpeedSp = 0.32,
            Pressure = 0.33,
            PressureIdle = 0.34,
            PressureSp = 0.35,
            AxialLoad = 0.36,
            AxialLoadSp = 0.37,
            AxialLoadLimitMax = 0.38,
            RotorTorque = 0.39,
            RotorTorqueSp = 0.231,
            RotorTorqueLimitMax = 0.232,
            RotorSpeed = 0.234,
            Flow = 0.237,
            IdFeedRegulator = LimitingParameterDto.AxialLoad,
            EnabledSubsystems = 15,
            HasOscillation = false,
        }
    };
    
    public ProcessMapReportDataSaubStatServiceTest()
    {
        wellService.GetOrDefaultAsync(Arg.Any<int>(), Arg.Any<CancellationToken>())
            .Returns(well);

        processMapPlanBaseRepository.Get(Arg.Any<ProcessMapPlanBaseRequestWithWell>(), Arg.Any<CancellationToken>())
            .Returns(processMapPlan);

        wellOperationRepository.GetAsync(Arg.Any<WellOperationRequest>(), Arg.Any<CancellationToken>())
            .Returns(operations);

        wellOperationRepository.GetSectionTypes()
            .Returns(sectionTypes);

        wellOperationCategoryRepository.Get(Arg.Any<bool>())
            .Returns(operationCategories);

        dataSaubStatRepository.GetAsync(Arg.Any<int>(), Arg.Any<DateTimeOffset>(), Arg.Any<DateTimeOffset>(), Arg.Any<CancellationToken>())
            .Returns(dataSaubStat);

        service = new ProcessMapReportDrillingService(wellService, processMapPlanBaseRepository, dataSaubStatRepository, wellOperationRepository, wellOperationCategoryRepository);
    }

    [Fact]
    public async Task GetAsync_return_data()
    {
        // arrange
        DataSaubStatRequest request = new() { };

        // act
        var result = await service.GetAsync(well.Id, request, CancellationToken.None);

        // assert
        Assert.NotEmpty(result);
    }
}