using KYFramework;
using SimulationServer.Utils;

namespace SimulationServer;

public class MHRescueMission : Entity
{
    public List<AircraftEntity> aircrafts = new List<AircraftEntity>();
    public Action End;
    public bool IsRunning = false;

    #region 仿真程序
    public int SimulationTime = 1;
    #endregion
    
    #region 任务信息
    public string MissionId; // 任务ID
    public bool Success; // 任务是否成功
    public double SimTime;
    public double InitArea;
    // 火场点
    public FireGround FireGround;
    public double slope;
    public double area;
    public double tn;
    public List<string> successes = new List<string>();
    #endregion
    
    #region 报告

    // 灭火的 单机能力
    // <机型,<sheet,<指标名,值列表>>>
    public Dictionary<string,Dictionary<string,Dictionary<string,List<string>>>> singleReport =  new ();
    // 灭火的 整体能力
    // <sheet,<指标名,值列表>>
    public Dictionary<string, Dictionary<string, List<string>>> totalReport = new ();
    //装备指标
    // <sheet,<指标名,值列表>>
    public Dictionary<string, Dictionary<string, List<string>>> equipReport = new ();

    #endregion

    public void Reset()
    {
        SimTime = 0;
        area = 0;
        tn = 0;
        FireGround.countArea.burnarea = InitArea;
        aircrafts?.ForEach(a => a.Reset());
    }
    
    public void Start()
    {
        Log.Info($"{MissionId} 任务开始!");
        aircrafts?.ForEach(a => a.Start());
        IsRunning = true;
    }
    
    public void EndMission()
    {
        IsRunning = false;
        Log.Info($"{MissionId} 任务结束!");
        // 灭火完成 任务结束
        End?.Invoke();
        
        SaveMH();
        
        SaveTotalMH();
        
        ReportMH();

        var readyTime = aircrafts.First().TaskReadyTime;
        Task.Delay(TimeSpan.FromSeconds(readyTime)).ContinueWith(t => this.StartAsyncMH());
    }

    
    /// <summary>
    /// 任务结束一次指标报告
    /// </summary>
    public void SaveMH()
    {
        foreach (AircraftEntity aircraftEntity in aircrafts)
        {
            // 输出 area
            var staticCapacity = aircraftEntity.GetComponent<StaticCapacityComponent>();
            var taskPerformance = aircraftEntity.GetComponent<TaskPerformanceComponent>();
            var economical = aircraftEntity.GetComponent<EconomicalComponent>();

            if(staticCapacity == null || taskPerformance == null || economical == null) continue;
            
            staticCapacity.FillData(aircraftEntity.Db);
            taskPerformance.FillData(aircraftEntity.Db);
            economical.FillData();

            string key = aircraftEntity.AircraftId;
            
            if (!singleReport.ContainsKey(key))
            {
                singleReport[key] = new Dictionary<string, Dictionary<string, List<string>>>();
            }
           
            Dictionary<string, Dictionary<string, string>> staticReport = staticCapacity.GetReport();
            foreach (var kv in staticReport)
            {
                if(!singleReport[key].ContainsKey(kv.Key)) singleReport[key][kv.Key] = new Dictionary<string, List<string>>();
                foreach (var kv2 in kv.Value)
                {
                    if (!singleReport[key][kv.Key].ContainsKey(kv2.Key)) singleReport[key][kv.Key][kv2.Key] = new List<string>();
                    singleReport[key][kv.Key][kv2.Key].Add(kv2.Value);
                }
            }
           
            Dictionary<string, Dictionary<string, string>> taskReport = taskPerformance.GetReport();
            foreach (var kv in taskReport)
            {
                if(!singleReport[key].ContainsKey(kv.Key)) singleReport[key][kv.Key] = new Dictionary<string, List<string>>();
                foreach (var kv2 in kv.Value)
                {
                    if (!singleReport[key][kv.Key].ContainsKey(kv2.Key)) singleReport[key][kv.Key][kv2.Key] = new List<string>();
                    singleReport[key][kv.Key][kv2.Key].Add(kv2.Value);
                }
            }

            Dictionary<string, Dictionary<string, string>> economicalReport = economical.GetReport();
            
            foreach (var kv in economicalReport)
            {
                if(!singleReport[key].ContainsKey(kv.Key)) singleReport[key][kv.Key] = new Dictionary<string, List<string>>();
                foreach (var kv2 in kv.Value)
                {
                    if (!singleReport[key][kv.Key].ContainsKey(kv2.Key)) singleReport[key][kv.Key][kv2.Key] = new List<string>();
                    singleReport[key][kv.Key][kv2.Key].Add(kv2.Value);
                }
            }
        }
    }

    public void SaveTotalMH()
    {
        var totalPerformance = GetComponent<TotalTaskPerformanceComponent>();
        totalPerformance.FillData();
        var totalPerformanceReport = totalPerformance.GetReport();
        foreach (var kv in totalPerformanceReport)
        {
            if(!totalReport.ContainsKey(kv.Key)) totalReport[kv.Key] = new Dictionary<string, List<string>>();
            
            foreach (var kv2 in kv.Value)
            {
                if (!totalReport[kv.Key].ContainsKey(kv2.Key)) totalReport[kv.Key][kv2.Key] = new List<string>();
                
                if(kv2.Key == "任务成功率/-")
                {
                    successes.Add(kv2.Value);
                } 
                totalReport[kv.Key][kv2.Key].Add(kv2.Value);
            }
        }
        
        var TotalEconomical = GetComponent<TotalEconomicalComponent>();
        TotalEconomical.FillData();
        var totalEconomicalReport = TotalEconomical.GetReport();
        foreach (var kv in totalEconomicalReport)
        {
            if(!totalReport.ContainsKey(kv.Key)) totalReport[kv.Key] = new Dictionary<string, List<string>>();
            foreach (var kv2 in kv.Value)
            {
                if (!totalReport[kv.Key].ContainsKey(kv2.Key)) totalReport[kv.Key][kv2.Key] = new List<string>();
                totalReport[kv.Key][kv2.Key].Add(kv2.Value);
            }
        }
        
        var TotalEquipment = GetComponent<EquipmentComponent>();
        TotalEquipment.FillData();
        var totalEquipmentReport = TotalEquipment.GetReport();
        foreach (var kv in totalEquipmentReport)
        {
            if(!equipReport.ContainsKey(kv.Key)) equipReport[kv.Key] = new Dictionary<string, List<string>>();
            foreach (var kv2 in kv.Value)
            {
                if (!equipReport[kv.Key].ContainsKey(kv2.Key)) equipReport[kv.Key][kv2.Key] = new List<string>();
                equipReport[kv.Key][kv2.Key].Add(kv2.Value);
            }
        }
    }
    
    public float getSuccessRate()
    {
        int count = 0;
        foreach (string success in successes)
        {
            if(success == "成功")
            {
                count++;
            }
        }

        return count / successes.Count;
    }

    public void ReportMH()
    {
        string data = DateTime.Now.ToString("yyyy-MM-dd");
        string path = $"Reports/MH/{data}/{MissionId}";
        if(!Directory.Exists(path)) Directory.CreateDirectory(path);
        foreach (var kv in singleReport)
        {
            string filePath = $"{path}/{kv.Key}灭火任务单机指标报告.xls";
            DataTableExtensions.SaveToExcel(filePath, kv.Value);
        }

        foreach (KeyValuePair<string,Dictionary<string,List<string>>> keyValuePair in totalReport)
        {
            foreach (KeyValuePair<string,List<string>> kv in keyValuePair.Value)
            {
                if(kv.Key == "任务成功率/-")
                {
                    double successRate = getSuccessRate();
                    kv.Value.Add((successRate * 100) + "%");
                }
                else
                {
                    List<string> values = kv.Value;
                    double sum = 0;
                    foreach (string value in values)
                    {
                        if (double.TryParse(value, out double num))
                        {
                            sum += num;
                        }
                    }
                    double average = sum / values.Count;
                    values.Add(average.ToString("#0.00"));
                }
            }
        }
        
        
        string totalPath = $"{path}/{"灭火任务总体指标报告"}.xls";
        DataTableExtensions.SaveToExcel(totalPath, totalReport,true);
        
        string equicPath = $"{path}/{"装备体系评估报告"}.xls";
        DataTableExtensions.SaveToExcel(equicPath, equipReport);
    }
}

[ObjectSystem]
public class MhRescueMissionAwakeSystem : AwakeSystem<MHRescueMission,FireGround,double>
{
    public override void Awake(MHRescueMission self, FireGround fire, double initArea)
    {
        self.FireGround = fire;
        self.InitArea = initArea;
    }
}

[ObjectSystem]
public class RescueMissionUpdateSystem : UpdateSystem<MHRescueMission>
{
    public override void Update(MHRescueMission self)
    {
        if(!self.IsRunning) return;
        if (self.FireGround.countArea.burnarea <= 0)
        {
            self.Success = true;
            self.EndMission();
            return;
        }

        if(self.tn >= 10 * 60 * 60)
        {
            self.Success = false;
            self.EndMission();
            return;
        }
        
        self.aircrafts.Sort((a, b) => a.T.CompareTo(b.T));
        self.aircrafts.ForEach(a => a.Update(self.SimTime));
        self.SimTime += 1 * TaskComponent.Speed;
    }
}