using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AsbCloudApp.Data;
using AsbCloudApp.Data.SAUB;
using AsbCloudApp.Repositories;
using AsbCloudApp.Requests;
using AsbCloudApp.Services;

namespace AsbCloudInfrastructure.Services;

public class WellboreService : IWellboreService
{
	const string WellboreNameFormat = "Ствол {0}";
	private readonly IWellService wellService;
	private readonly IWellOperationRepository wellOperationRepository;
    private readonly ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache;

    public WellboreService(
		IWellService wellService, 
		IWellOperationRepository wellOperationRepository, 
		ITelemetryDataCache<TelemetryDataSaubDto> telemetryDataCache)
	{
		this.wellService = wellService;
		this.wellOperationRepository = wellOperationRepository;
        this.telemetryDataCache = telemetryDataCache;
    }

	public async Task<IEnumerable<WellboreDto>> GetWellboresAsync(IEnumerable<int> idsWells,
		CancellationToken token)
	{
		var wellRequest = new WellRequest { Ids = idsWells };
		var wells = await wellService.GetAsync(wellRequest, token);

        var rowSections = await wellOperationRepository.GetSectionsAsync(idsWells, token);
		var groupedSections = rowSections
			.Where(section => section.IdType == 1)
			.GroupBy(s => s.IdWell);

		var wellbores = wells
            .SelectMany(well => {
				var wellSections = groupedSections.FirstOrDefault(group => group.Key == well.Id);
				if (wellSections is not null)
					return MakeWellboreBySections(wellSections, well);
				else
					return MakeWellboreDefault(well);
            })
			.OrderBy(w => w.Well.Id)
			.ThenBy(w => w.Id);

		return wellbores;
    }

    private IEnumerable<WellboreDto> MakeWellboreDefault(WellDto well)
    {
		var wellbore = new WellboreDto {
			Id = 1,
			Name = string.Format(WellboreNameFormat, 1),
			Well = well,
        };
		//if(well.)

		if(well.IdTelemetry is not null)
		{
			var dataCache = telemetryDataCache.GetOrDefaultFirstLast(well.IdTelemetry.Value);
			if (dataCache is not null)
			{
				wellbore.DateStart = dataCache.Value.First.DateTime;
				wellbore.DepthStart = dataCache.Value.First.WellDepth;

                wellbore.DateEnd = dataCache.Value.Last.DateTime;
                wellbore.DepthEnd = dataCache.Value.Last.WellDepth;
            }
		}

        return new[] { wellbore };
    }

    private IEnumerable<WellboreDto> MakeWellboreBySections(IEnumerable<SectionByOperationsDto> sections, WellDto well)
    {
		var orderedSections = sections.OrderBy(s => s.DateStart);
		var wellbores = new List<WellboreDto>();
		int wellboreId = 1;

		SectionByOperationsDto? preSection = null;
		WellboreDto? wellbore = null;

        foreach (var section in orderedSections)
		{
			if (wellbore is null || wellbore.DepthEnd > section.DepthStart)
			{
                wellbore = new WellboreDto
                {
                    Name = string.Format(WellboreNameFormat, wellboreId),
                    Id = wellboreId,
                    Well = well,

                    DateStart = section.DateStart,
                    DateEnd = section.DateEnd,
                    DepthStart = section.DepthStart,
                    DepthEnd = section.DepthEnd,
                };

                wellbores.Add(wellbore);
                wellboreId++;

            }
			else
			{
				wellbore.DepthEnd = section.DepthEnd;
				wellbore.DateEnd = section.DateEnd;
			}

            preSection = section;
        }

        if (wellbore is not null)
		{
            if (well.IdTelemetry is not null)
            {
                var dataCache = telemetryDataCache.GetOrDefaultFirstLast(well.IdTelemetry.Value);
                if (dataCache is not null)
                {
                    wellbore.DateEnd = dataCache.Value.Last.DateTime;
                    wellbore.DepthEnd = dataCache.Value.Last.WellDepth;
                }
            }
        }        

        return wellbores;
    }
}