using ReportingServices.Shared.Models.ProductionReport;

namespace ReportingServices.Shared.ViewModels.ProductionReport;

public class ToolEventView
{
    public string Reactor { get; set; }
    public string Type { get; set; }
    public string StartDate { get; set; }
    public string EndDate { get; set; }
    public double Downtime { get; set; }
    public bool IsInProduction { get; set; }
    public List<ReactorEvent> Events { get; set; }
    public ReactorEvent MostRecentEvent { get; set; }
    public List<ToolUptimeData> Uptime { get; set; }

    public ToolEventView(List<ReactorEvent> events, string startDate, string endDate, string reactor, string type)
    {
        Events = events;
        StartDate = startDate;
        EndDate = endDate;
        Reactor = reactor;
        Type = type;
        MostRecentEvent = events[^1];
        IsInProduction = EventIsProduction(MostRecentEvent.REACT_MODE);
        Uptime = DetermineToolUptimeData();
    }

    public void SetDowntime(int timeSinceLastUpTransaction)
    {
        if (IsInProduction)
            Downtime = 0;
        else
            Downtime = (double)timeSinceLastUpTransaction / 60;
    }

    public List<ToolUptimeData> DetermineToolUptimeData()
    {
        List<ToolUptimeData> data = new();

        bool currentModeIsUp;
        double uptime = 0;
        DateTime compareDate = DateTime.Parse(StartDate).Date;
        DateTime previousTransaction = DateTime.Parse(StartDate).Date;

        currentModeIsUp = EventIsProduction(Events[0].REACT_MODE);

        if (Events.Count == 1)
            data = LoadUptimeData(currentModeIsUp);

        for (int i = 1; i < Events.Count; i++)
        {
            DateTime currentTransaction = DateTime.Parse(Events[i].EVENT_DTM);

            if (currentTransaction.Date == compareDate)
            {
                if (currentModeIsUp)
                    uptime += (DateTime.Parse(Events[i].EVENT_DTM) - previousTransaction).TotalMinutes;

                currentModeIsUp = EventIsProduction(Events[i].REACT_MODE);
                previousTransaction = DateTime.Parse(Events[i].EVENT_DTM);
            }

            if ((currentTransaction.Date - compareDate).TotalHours == 24)
            {
                if (currentModeIsUp)
                    uptime += (currentTransaction.Date - previousTransaction).TotalMinutes;

                data.Add(new ToolUptimeData
                {
                    Date = compareDate.ToString(),
                    UptimePercentage = uptime / 1440
                });

                if (currentModeIsUp)
                    uptime = (currentTransaction - currentTransaction.Date).TotalMinutes;
                else
                    uptime = 0;

                compareDate = compareDate.AddDays(1);
                currentModeIsUp = EventIsProduction(Events[i].REACT_MODE);
                previousTransaction = DateTime.Parse(Events[i].EVENT_DTM);
            }

            if ((currentTransaction.Date - compareDate).TotalHours > 24)
            {
                while (currentTransaction.Date != compareDate)
                {
                    if (currentModeIsUp)
                        uptime += (compareDate.AddDays(1) - previousTransaction).TotalMinutes;

                    data.Add(new ToolUptimeData
                    {
                        Date = compareDate.ToString(),
                        UptimePercentage = uptime / 1440
                    });

                    uptime = 0;

                    compareDate = compareDate.AddDays(1);
                    previousTransaction = compareDate;
                }
            }

            if (i == Events.Count - 1)
            {
                if (DateTime.Parse(EndDate).Date != compareDate)
                {
                    while (DateTime.Parse(EndDate).Date != compareDate)
                    {
                        if (currentModeIsUp)
                            uptime += (compareDate.AddDays(1) - previousTransaction).TotalMinutes;

                        data.Add(new ToolUptimeData
                        {
                            Date = compareDate.ToString(),
                            UptimePercentage = uptime / 1440
                        });

                        uptime = 0;

                        compareDate = compareDate.AddDays(1);
                        previousTransaction = compareDate;
                    }
                }

                if (currentModeIsUp)
                    uptime += (DateTime.Parse(EndDate) - previousTransaction).TotalMinutes;

                data.Add(new ToolUptimeData
                {
                    Date = DateTime.Now.Date.ToString(),
                    UptimePercentage = uptime / (DateTime.Parse(EndDate) - DateTime.Parse(EndDate).Date).TotalMinutes
                });

            }
        }

        return data;
    }

    private List<ToolUptimeData> LoadUptimeData(bool currentModeIsUp)
    {
        List<ToolUptimeData> data = new();

        double days = (DateTime.Parse(EndDate) - DateTime.Parse(StartDate)).TotalDays;

        for (int i = 0; i < days; i++)
        {
            data.Add(new ToolUptimeData
            {
                Date = DateTime.Parse(StartDate).Date.AddDays(i).ToString(),
                UptimePercentage = currentModeIsUp ? 1 : 0
            });
        }

        return data;
    }

    private bool EventIsProduction(string evnt)
    {
        if (evnt.ToUpper() == "UP")
            return true;

        if (evnt.ToUpper() == "UP_WITH_INCREASED_SAMPLING")
            return true;

        if (evnt.ToUpper() == "IDLE")
            return true;

        if (evnt.ToUpper() == "ENGINEERING_DEVELOPMENT")
            return true;

        return false;
    }

}