using KYFramework;
using NPOI.SS.Formula.PTG;
using SimulationServer.Utils;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace SimulationServer;

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

    public bool IsRunning;
    public double SimulationTime;

    public Dictionary<string, Dictionary<string, Dictionary<string, List<string>>>> singleReport = 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} 任务结束!");

        if (currentExecuteCount > ExecutionContext)
        {
            return;
        }

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

        if (currentExecuteCount == ExecutionContext)
        {
            SaveSJ();
            SaveAircraftSJDatas();
            ReportSJ();
            IsOver = true;
            return;
        }

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

    public void SaveAircraftSJDatas()
    {
        foreach (AircraftDY 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("0");
            if (!aircraftSJDatas[key].ContainsKey("识别数量"))
                aircraftSJDatas[key]["识别数量"] = new List<string>();
            aircraftSJDatas[key]["识别数量"].Add("0");
            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("0");
            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());
            if (!aircraftSJDatas[key].ContainsKey("人员存活率"))
                aircraftSJDatas[key]["人员存活率"] = new List<string>();
            aircraftSJDatas[key]["人员存活率"].Add(aircraftEntity.Success ? aircraftEntity.targetCount.ToString() : "0");
        }
    }

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

            if (staticCapacity == null) continue;

            staticCapacity.FillData2(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.GetReport2();
            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 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);
        }
    }
}


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

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

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