using ReportingServices.Shared.HelperClasses;
using ReportingServices.Shared.Models.ProductionReport;
using ReportingServices.Shared.ViewModels.ProductionReport;

namespace ReportingServices.Shared.ViewModels.ProductionReport
{
    public class DailyReport
    {
        public DateTime StartDate { get; set; }
        public YieldStatistics CurrentWeek { get; set; }
        public YieldStatistics PreviousWeek { get; set; }
        public Dictionary<string, List<EquipmentStateByDay>> ToolAvailibilityByType { get; set; }
        public Dictionary<string, ToolStateByType> ToolStateByType { get; set; }
        public Dictionary<string, List<string>> ToolStatesByOwner { get; set; }
        public Dictionary<string, List<int>> DualLayerReactors { get; set; }
        public ManualReportEntries ManualReportEntries { get; set; }
        public List<UnloadTempsByDay> UnloadTempsByDay { get; set; }
        public List<SLLTool> SLLTools { get; set; }
        public int NumberOfToolsWaferSize6IN { get; set; }
        public int NumberOfToolsWaferSize8IN { get; set; }
        public int NumberOfToolsWaferSize6INScheduled { get; set; }
        public int NumberOfToolsWaferSize8INScheduled { get; set; }
        public QuarterlyTargets QuarterlyTargets { get; set; }

        public DailyReport()
        {
            ToolAvailibilityByType = new();
            ToolStateByType = new();
            DualLayerReactors = new();
            UnloadTempsByDay = new();
            StartDate = DateTime.Parse(APIHelperFunctions.GetBeginningOfWeekAsAPIString());
            CurrentWeek = new(StartDate, true);
            PreviousWeek = new(StartDate.AddDays(-7), false);
        }

        public void AddToolAvailibilityByType(string key, List<EquipmentStateByDay> states)
        {
            ToolAvailibilityByType.Add(key, states);
        }

        public void AddToolStateByType(string key, List<ToolStateCurrent> states)
        {
            ToolStateByType state = new(states);

            ToolStateByType.Add(key, state);
        }

        public void SetReactorInfo(List<Reactor> reactors, List<int> unscheduledReactors)
        {
            SetToolsByPocketSize(reactors, unscheduledReactors);
            SetDisabledLoadlocks(reactors);
        }

        public void SetRDSInfo(List<RDS> rdsList)
        {
            SetDualLayerReactors(rdsList);
            SetUnloadTempsLessThan700(rdsList);
        }

        private void SetToolsByPocketSize(List<Reactor> reactors, List<int> unscheduledReactors)
        {
            NumberOfToolsWaferSize6IN = reactors.Where(react => react.PocketSize.Contains("150")).Count();
            NumberOfToolsWaferSize8IN = reactors.Where(react => react.PocketSize.Contains("200")).Count();

            NumberOfToolsWaferSize6INScheduled =
                reactors.Where(react => !unscheduledReactors.Contains(react.ReactorNumber)
                && react.PocketSize.Contains("150")).Count();
            NumberOfToolsWaferSize8INScheduled =
                reactors.Where(react => !unscheduledReactors.Contains(react.ReactorNumber)
                && react.PocketSize.Contains("200")).Count();
        }

        private void SetDisabledLoadlocks(List<Reactor> reactors)
        {
            List<Reactor> reactorsWithDisabledLoadlocks = reactors.Where(react => react.HasDisabledLoadlock).ToList();

            int singleLoadlockASM = reactorsWithDisabledLoadlocks.Where(react => react.Type.Contains("ASM")).Count();
            int singleLoadlockHTR = reactorsWithDisabledLoadlocks.Where(react => react.Type.Contains("HTR")).Count();

            foreach (SLLTool sll in SLLTools)
            {
                if (sll.Date.Date == DateTime.Now.Date)
                {
                    sll.ASM = singleLoadlockASM;
                    sll.HTR = singleLoadlockHTR;
                    return;
                }
            }

            SLLTools.Add(new SLLTool
            {
                Date = DateTime.Now.Date,
                ASM = singleLoadlockASM,
                HTR = singleLoadlockHTR
            });
        }

        private void SetDualLayerReactors(List<RDS> rdsList)
        {
            DateTime compareDate = DateTime.Now.Date;
            List<RDS> rdsWithDualLayerPSN = rdsList.Where(rds => rds.LayerType.Contains("2 Layer") && rds.DateOut == compareDate).ToList();

            DualLayerReactors.Add("ASM", rdsWithDualLayerPSN.
                Where(rds => rds.ReactorType.Contains("ASM")).
                OrderBy(rds => rds.Reactor).
                Select(rds => rds.Reactor).
                Distinct().ToList());
            DualLayerReactors.Add("HTR", rdsWithDualLayerPSN.
                Where(rds => rds.ReactorType.Contains("HTR")).
                OrderBy(rds => rds.Reactor).
                Select(rds => rds.Reactor).
                Distinct().ToList());
            DualLayerReactors.Add("EPP", rdsWithDualLayerPSN.
                Where(rds => rds.ReactorType.Contains("EPP")).
                OrderBy(rds => rds.Reactor).
                Select(rds => rds.Reactor).
                Distinct().ToList());
        }

        private void SetUnloadTempsLessThan700(List<RDS> rdsList)
        {
            var rdsWithTempsLessThan700 = rdsList.Where(rds => rds.UnloadTemp < 700).GroupBy(rds => rds.DateOut);

            foreach (var group in rdsWithTempsLessThan700)
            {
                UnloadTempsByDay.Add(new UnloadTempsByDay
                {
                    Date = group.Key,
                    ASMUnloadsBelow700 = group.Where(rds => rds.ReactorType.Contains("ASM")).Select(rds => rds.Reactor).Distinct().Count(),
                    HTRUnloadsBelow700 = group.Where(rds => rds.ReactorType.Contains("HTR")).Select(rds => rds.Reactor).Distinct().Count()
                });
            }
        }

        public void ReverseLists()
        {
            CurrentWeek.ScrapByDay = APIHelperFunctions.ReverseList(CurrentWeek.ScrapByDay);
            PreviousWeek.ScrapByDay = APIHelperFunctions.ReverseList(PreviousWeek.ScrapByDay);

            ToolAvailibilityByType["ASM"] = APIHelperFunctions.ReverseList(ToolAvailibilityByType["ASM"]);
            ToolAvailibilityByType["EPP"] = APIHelperFunctions.ReverseList(ToolAvailibilityByType["EPP"]);
            ToolAvailibilityByType["HTR"] = APIHelperFunctions.ReverseList(ToolAvailibilityByType["HTR"]);
        }
    }
}
