using System;
using AsbCloudApp.Data.SAUB;

namespace AsbCloudInfrastructure.Services.ProcessMaps.Report.Data;

internal class TelemetryStat
{
    public ParamStat Pressure { get; }
    public ParamStat AxialLoad { get; }
    public ParamStat RotorTorque { get; }
    public ParamStat BlockSpeed { get; }

    private TelemetryDataSaubStatDto? previous;
    private double depthSum = 0d;
    private double hoursSum = 0d;

    public double? Rop => hoursSum == 0d ? null : depthSum / hoursSum;

    private double depthWithSaub = 0d;
    public double UsageSaub { get; }
    public double UsagePredictPlan { get; }
    public DateTime DateStart { get; }
    public float DeltaDepth { get; }
    public int IdMode { get; }
    public string ModeName { get; }
    public double DrillingHours { get; }

    public TelemetryStat(Span<TelemetryDataSaubStatDto> telemetry)
    {
        var telemetryFirst = telemetry[0];
        var telemetryLast = telemetry[^1];

        IdMode = telemetryFirst.IdMode;
        ModeName = GetModeName(IdMode);
        DateStart = telemetryFirst.DateMin;
        DeltaDepth = telemetryLast.WellDepthMax - telemetryFirst.WellDepthMin;
        DrillingHours = (telemetryLast.DateMax - telemetryFirst.DateMin).TotalHours;

        BlockSpeed = new(t => t.BlockSpeedSp, t => t.BlockSpeed, null, 1, IdMode);
        Pressure = new(t => t.PressureSpDelta, t => t.PressureDelta, t => t.PressureDeltaLimitMax, 2, IdMode);
        RotorTorque = new(t => t.RotorTorqueSp, t => t.RotorTorque, t => t.RotorTorqueLimitMax, 3, IdMode);
        AxialLoad = new(t => t.AxialLoadSp, t => t.AxialLoad, t => t.AxialLoadLimitMax, 4, IdMode);

        foreach (var t in telemetry)
            UpdateStat(t);

        UsageSaub = 100d * depthWithSaub / depthSum;
        UsagePredictPlan = IdMode != 0 ? 100d : 0d;
    }

    private void UpdateStat(TelemetryDataSaubStatDto current)
    {
        if (previous is not null)
        {
            var deltaDepth = current.WellDepthMin - previous.WellDepthMin;

            if (deltaDepth > 0)
            {
                var deltaHours = (current.DateMin - previous.DateMax).TotalHours;
                depthSum += deltaDepth;
                hoursSum += deltaHours;

                if (current.IdMode == 1 || current.IdMode == 3)
                    depthWithSaub += deltaDepth;
            }
        }

        previous = current;
        Pressure.UpdateStat(current);
        AxialLoad.UpdateStat(current);
        RotorTorque.UpdateStat(current);
        BlockSpeed.UpdateStat(current);
    }

    private static string GetModeName(int idMode)
        => idMode switch
        {
            1 => "Ротор",
            3 => "Слайд",
            _ => "Ручной",
        };
}