using KYFramework;
using NPOI.SS.Formula.PTG;
using SimulationServer.Utils;

namespace SimulationServer;

public class SeaSJRescueMission : Entity
{
    public string MissionId; // 任务ID
    public bool Success; // 任务是否成功
    public List<AircraftSJ> aircrafts = new List<AircraftSJ>();

    public bool IsRunning;
    public double SimulationTime;

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

    public Dictionary<string, Dictionary<string, List<string>>> aircraftSJDatas = new();

    public bool IsOver = false;

    private int currentExecuteCount = 1;
    public int ExecutionContext = 0;

    public string date;
    public void Start()
    {
        IsRunning = true;
        aircrafts.ForEach(a => a.Start());
        Log.Info($"{MissionId} 任务开始!");
    }

    public void Reset()
    {
        SimulationTime = 0;
        aircrafts?.ForEach(a => a.Reset());
    }

    public void EndMission()
    {
        IsRunning = false;
        Log.Info($"{MissionId} 任务结束!");

        //SaveSJ();
        //SaveTotalMH();
        //ReportSJ();

        if (currentExecuteCount > ExecutionContext)
        {
            return;
        }

        if (currentExecuteCount < ExecutionContext)
        {
            SaveSJ();
            //SaveTotalMH();
            SaveAircraftSJDatas();
        }

        if (currentExecuteCount == ExecutionContext)
        {
            SaveSJ();
            SaveAircraftSJDatas();
            //SaveTotalMH();
            ReportSJ();
            //this.StartAsyncMH();
            IsOver = true;
            return;
        }

        this.Reset();
        this.Start();
        currentExecuteCount++;



        // var readyTime = AircraftXHs.First().TaskReadyTime;
        // Task.Delay(TimeSpan.FromSeconds(readyTime)).ContinueWith(t => this.StartAsyncXH());
    }

    public void SaveAircraftSJDatas()
    {
        foreach (AircraftSJ aircraftEntity in aircrafts)
        {
            string key = aircraftEntity.AircraftId;
            if (!aircraftSJDatas.ContainsKey(key))
            {
                aircraftSJDatas[key] = new Dictionary<string, List<string>>();
            }
            if (!aircraftSJDatas[key].ContainsKey("识别成功率"))
                aircraftSJDatas[key]["识别成功率"] = new List<string>();
            aircraftSJDatas[key]["识别成功率"].Add(aircraftEntity.isseePerson ? aircraftEntity.sbCount.ToString() : "0");
            if (!aircraftSJDatas[key].ContainsKey("识别数量"))
                aircraftSJDatas[key]["识别数量"] = new List<string>();
            aircraftSJDatas[key]["识别数量"].Add(aircraftEntity.sbCount.ToString());
            if (!aircraftSJDatas[key].ContainsKey("人员数量"))
                aircraftSJDatas[key]["人员数量"] = new List<string>();
            aircraftSJDatas[key]["人员数量"].Add(aircraftEntity.targetCount.ToString());
            if (!aircraftSJDatas[key].ContainsKey("任务准备时间"))
                aircraftSJDatas[key]["任务准备时间"] = new List<string>();
            aircraftSJDatas[key]["任务准备时间"].Add(aircraftEntity.TaskReadyTime.ToString());
            if (!aircraftSJDatas[key].ContainsKey("平均搜索时间"))
                aircraftSJDatas[key]["平均搜索时间"] = new List<string>();
            aircraftSJDatas[key]["平均搜索时间"].Add(aircraftEntity.SearchTime.ToString("f4"));
            if (!aircraftSJDatas[key].ContainsKey("平均救助时间"))
                aircraftSJDatas[key]["平均救助时间"] = new List<string>();
            aircraftSJDatas[key]["平均救助时间"].Add(aircraftEntity.resulttime.ToString());
            if (!aircraftSJDatas[key].ContainsKey("总飞行时间"))
                aircraftSJDatas[key]["总飞行时间"] = new List<string>();
            aircraftSJDatas[key]["总飞行时间"].Add(aircraftEntity.TotalTime.ToString("f4"));
            if (!aircraftSJDatas[key].ContainsKey("人员存活率"))
                aircraftSJDatas[key]["人员存活率"] = new List<string>();
            aircraftSJDatas[key]["人员存活率"].Add(aircraftEntity.Success ? aircraftEntity.targetCount.ToString() : "0");
            if (!aircraftSJDatas[key].ContainsKey("海上搜索覆盖面积"))
                aircraftSJDatas[key]["海上搜索覆盖面积"] = new List<string>();
            aircraftSJDatas[key]["海上搜索覆盖面积"].Add(aircraftEntity.seaArea.ToString());
        }
    }

    public void SaveSJ()
    {
        foreach (AircraftSJ aircraftEntity in aircrafts)
        {
            var staticCapacity = aircraftEntity.GetComponent<SJStaticCapacityComponent>();

            if (staticCapacity == null) continue;

            staticCapacity.FillData(aircraftEntity.Db);

            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);
                }
            }
        }
        if (currentExecuteCount == ExecutionContext)
        {
            foreach (var kv in singleReport)
            {
                foreach (var kv2 in kv.Value)
                {
                    foreach (var kv3 in kv2.Value)
                    {
                        var sum = 0f;
                        foreach (var kv4 in kv3.Value)
                        {
                            bool isfloat = float.TryParse(kv4, out float f);
                            if (isfloat)
                                sum += float.Parse(kv4);
                            else
                                sum = -1f;
                        }
                        if (sum != -1f)
                            kv3.Value.Add((sum / kv3.Value.Count).ToString());
                        else
                            kv3.Value.Add("");
                    }
                }
            }
        }
    }

    public void SaveTotalMH()
    {
        var totalPerformance = GetComponent<SJTotalTaskPerformanceComponent>();
        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>();
                totalReport[kv.Key][kv2.Key].Add(kv2.Value);
            }
        }
    }

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

        //foreach (KeyValuePair<string, Dictionary<string, List<string>>> keyValuePair in totalReport)
        //{
        //    foreach (KeyValuePair<string, List<string>> kv in keyValuePair.Value)
        //    {
        //        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);
    }
}


[ObjectSystem]
public class SeaSJRescueMissionUpdateSystem : UpdateSystem<SeaSJRescueMission>
{
    public override void Update(SeaSJRescueMission self)
    {
        if (!self.IsRunning) return;

        self.aircrafts?.ForEach(a => a.Update(self.SimulationTime));

        if (self.aircrafts.All(a => a.IsOver))
        {
            self.EndMission();
        }
    }
}