using Aitex.Common.Util;
using Aitex.Core.RT.DBCore;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Aitex.Core.Common.DeviceData;
using Sicentury.Core;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Event;
using System.Linq;
using OfficeOpenXml;
using OfficeOpenXml.Style;

namespace ECF.Framework.Common.DBCore
{
    public class ProcessHistoryQuery
    {
        private static string _path = PathManager.GetAppDir() + "\\Export";

        public static void ExportRecipeProcessHistory(string module, string querType,string guid)
        {
            var qr = QueryRecipeProcessHistoryData(guid);

            var qp = QueryProcessHistoryData(qr, querType);

            var processHistoryItems = (List<ProcessDeviceItem>)DATA.Poll($"{module}.ProcessHistoryItemsDefault");

            ExportRecipe(module, qr, qp, processHistoryItems);
        }

        public static RecipeProcessHistoryData QueryRecipeProcessHistoryData(string guid)
        {
            string cmd =
                $"select * from process_data where guid='{guid}' and process_status='Succeed'";
            return GetPMRecipe(cmd);
        }

        //**********************************************时间区间内Recipe运行记录查询*************************************************************
        private static RecipeProcessHistoryData GetPMRecipe(string cmd)
        {
            try
            {
                var ds = DB.ExecuteDataSet(cmd);

                if (ds == null || ds.Tables[0].Rows.Count == 0)
                    return null;

                for (int i = 0; i < 1; i++)
                {
                    RecipeProcessHistoryData recipeProcessHistoryData = new RecipeProcessHistoryData()
                    {
                        PmModel = ds.Tables[0].Rows[i]["process_in"].ToString(),
                        XPath = ds.Tables[0].Rows[i]["recipe_name"].ToString(),
                        Status = ds.Tables[0].Rows[i]["process_status"].ToString(),
                        ProcessGuid = ds.Tables[0].Rows[i]["guid"].ToString(),
                        BeginTime = ds.Tables[0].Rows[i]["process_begin_time"].ToString(),
                        EndTime = ds.Tables[0].Rows[i]["process_end_time"].ToString(),
                        WaferDataGuid = ds.Tables[0].Rows[i]["wafer_data_guid"].ToString()
                    };
                    GetWaferInf(recipeProcessHistoryData);
                    return recipeProcessHistoryData;
                }
            }
            catch (Exception ex)
            {
                LOG.Write($"ProcessHistoryQuery: {ex}");
                return null;
            }

            return null;
        }

        private static void GetWaferInf(RecipeProcessHistoryData recipeProcessHistoryData)
        {
            string cmd = $"select * from wafer_data where wafer_id='{recipeProcessHistoryData.WaferDataGuid}' ";
            var ds = DB.ExecuteDataSet(cmd);
            if (ds == null || ds.Tables[0].Rows.Count == 0)
                return;
            recipeProcessHistoryData.WaferInf =
                $"{ds.Tables[0].Rows[0]["create_station"]}_{ds.Tables[0].Rows[0]["create_slot"]}";
            recipeProcessHistoryData.TrayInf =
                $"{ds.Tables[0].Rows[0]["create_station"]}_{ds.Tables[0].Rows[0]["create_slot"]}";
        }

        //**********************************************选中Recipe时，查询当时记录的总的步骤流程*************************************************
        public static List<ProcessHistoryData> QueryProcessHistoryData(RecipeProcessHistoryData recipeProcessHistoryData, string stepModel)
        {
            string cmd =
                $"select * from recipe_step_data where process_data_guid='{recipeProcessHistoryData.ProcessGuid}' order by step_begin_time asc ";
            return GetProcessHistoryDataList(cmd, recipeProcessHistoryData.Name, stepModel);
        }

        private static List<ProcessHistoryData> GetProcessHistoryDataList(string cmd, string recipeName,
            string stepModel)
        {
            List<ProcessHistoryData> processHistoryDataList =
                new List<ProcessHistoryData>();
            try
            {
                var ds = DB.ExecuteDataSet(cmd);
                if (ds == null || ds.Tables[0].Rows.Count == 0)
                    return null;

                for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                {
                    ProcessHistoryData recipeProcessHistoryData = new ProcessHistoryData()
                    {
                        StepBeginTime = ds.Tables[0].Rows[i]["step_begin_time"].ToString(),
                        StepEndTime = ds.Tables[0].Rows[i]["step_end_time"].ToString(),
                        RecipeName = recipeName,
                        StepName = ds.Tables[0].Rows[i]["step_name"].ToString(),
                        StepTime = ds.Tables[0].Rows[i]["step_time"].ToString(),
                        StepNumber = ds.Tables[0].Rows[i]["step_number"].ToString()
                    };

                    if (stepModel == "All") //All返回所有，*筛选出步骤名称中带有*
                        processHistoryDataList.Add(recipeProcessHistoryData);
                    else if (stepModel == "*")
                        if (recipeProcessHistoryData.StepName.Contains("*"))
                            processHistoryDataList.Add(recipeProcessHistoryData);
                }
            }
            catch (Exception)
            {
                return null;
            }

            return processHistoryDataList;
        }

        //************************************************单步时硬件数据结果查询*******************************************************************

        /// <summary>
        /// 拆分的天循查询数据
        /// </summary>
        /// <param name="daySlices">拆分的天</param>
        /// <param name="moduleName">PM名称</param>
        /// <param name="gasFlowSumList">显示列表对象</param>
        /// <returns></returns>
        public static List<ProcessHistoryDeviceData> GetProcessHistoryDeviceData(
            IEnumerable<DateRangeHelper> daySlices, string moduleName, List<ProcessDeviceItem> processHistoryItemList)
        {
            List<DataSet> dataSetList = new List<DataSet>();

            foreach (var daySlice in daySlices) //拆分天
            {
                var ds = GetProcessHistoryDeviceDataListDaySlices(daySlice, moduleName, processHistoryItemList);
                if (ds != null)
                    dataSetList.Add(ds); //拆分后，每次查询结果放入集合中
            }

            List<ProcessHistoryDeviceData> processHistoryDeviceDataList =
                new List<ProcessHistoryDeviceData>();

            foreach (var item in processHistoryItemList)
            {
                var phd = new ProcessHistoryDeviceData();
                phd.DeviceName = item.Display;
                phd.DATASubscribeName = item.Property;
                phd.Unit = item.Unit;
                phd.IsPropertyExists = item.IsPropertyExists;
                foreach (DataSet ds in dataSetList)
                {
                    for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
                    {
                        if (!item.IsPropertyExists)
                            continue;
                        string value = ds.Tables[0].Rows[i][$"{moduleName}.{item.Property}"].ToString();
                        if (value is not null && value.Length == 0)
                            continue;
                        float cache;
                        if (float.TryParse(value, out cache)) //防止非数据类型混入进来
                        {
                            phd.DeviceValue.Add(cache); //历史数据点
                            phd.TimeStamp.Add(ds.Tables[0].Rows[i]["time"].ToString()); //时间戳
                        }
                    }
                }

                if (phd.IsPropertyExists)
                {
                    phd.CalculateData();
                    processHistoryDeviceDataList.Add(phd);
                }
            }

            return processHistoryDeviceDataList;
        }

        /// <summary>
        /// 根据拆分的天循查询数据
        /// </summary>
        /// <param name="daySlices">拆分的天</param>
        /// <param name="moduleName">PM名称</param>
        /// <param name="gasFlowSumList">显示集合列表</param>
        /// <returns></returns>
        private static DataSet GetProcessHistoryDeviceDataListDaySlices(DateRangeHelper daySlices, string moduleName,
            List<ProcessDeviceItem> processHistoryItemList)
        {
            DataSet dataTable = null;
            var ts = daySlices.Diff;
            for (var day = 0; day <= ts.Days; day++)
            {
                var tblName = $"{daySlices.Start.AddDays(day):yyyyMMdd}.{moduleName}";
                var sql = new StringBuilder();
                // 检查表名是否存在，否则SQL执行出错。
                if (CheckTableExists(tblName))
                {
                    sql.Append("select time AS InternalTimeStamp");

                    // 添加待查询的列
                    foreach (var item in processHistoryItemList)
                    {
                        // 检查表中是否存在对应属性，否则SQL执行出错。
                        if (CheckPropertyExists(tblName, $"{moduleName}.{item.Property}"))
                        {
                            item.IsPropertyExists = true;
                            sql.Append("," + $"\"{moduleName}.{item.Property}\"");
                        }
                        else //不查询状态标记
                            item.IsPropertyExists = false;
                    }

                    sql.Append($", \"time\"");
                    sql.Append($" from \"{tblName}\"");

                    if (day < ts.Days)
                        sql.Append(" UNION ");
                    sql.Append(
                        $" where time between {daySlices.Start.Ticks} and {daySlices.End.Ticks}  order by InternalTimeStamp asc");
                    try
                    {
                        var ds = DB.ExecuteDataSet(sql.ToString());
                        if (ds is not null && ds.Tables[0].Rows.Count > 0)
                            dataTable = ds;
                    }
                    catch (Exception ex) //查询较早日期时，可能不存在属性会报错
                    {
                    }
                }
            }

            return dataTable;
        }

        private static bool CheckTableExists(string tableName)
        {
            var sql =
                $"SELECT EXISTS ( SELECT FROM pg_tables WHERE schemaname = 'public' AND tablename = '{tableName}' )";
            DataSet ds = DB.ExecuteDataSet(sql);
            if (ds == null)
                return false;

            if (ds.Tables[0].Rows.Count <= 0)
                return false;

            var value = ds.Tables[0].Rows[0]["exists"].ToString();
            if (value.ToLower() == "true")
                return true;

            return false;
        }

        private static bool CheckPropertyExists(string tableName, string property)
        {
            var sql =
                $"select count(1) from information_schema.columns WHERE  table_name = '{tableName}' and column_name = '{property}'";
            DataSet ds = DB.ExecuteDataSet(sql);
            if (ds == null)
                return false;

            if (ds.Tables[0].Rows.Count <= 0)
                return false;

            var value = int.Parse(ds.Tables[0].Rows[0]["count"].ToString());
            if (value == 0)
                return false;
            return true;
        }

        public static void ExportRecipe(string module, RecipeProcessHistoryData recipeProcessHistoryData, List<ProcessHistoryData> processHistoryDatas, List<ProcessDeviceItem> pmItemList)
        {
            Task.Run(() =>
            {
                try
                {
                    List<List<ProcessHistoryDeviceData>> exportRecipeProcessHistoryData = new();

                    for (int i = 0; i < processHistoryDatas.Count; i++)
                    {
                        var qeph = ProcessHistoryQuery.QueryExportProcessHistory(processHistoryDatas[i], module, pmItemList);
                        if (qeph == null)
                            continue;
                        foreach (var data in qeph)
                        {
                            data.StepNumber = processHistoryDatas[i].StepNumber;
                            data.StepName = processHistoryDatas[i].StepName;
                        }

                        exportRecipeProcessHistoryData.Add(qeph);
                    }

                    if (exportRecipeProcessHistoryData.Count > 0)
                    {
                        SaveCsv(exportRecipeProcessHistoryData, recipeProcessHistoryData);
                        //SaveExcel(exportRecipeProcessHistoryData, recipeProcessHistoryData);
                        EV.PostInfoLog(module, "Export recipe complete");
                    }
                    
                }
                catch (Exception ex)
                {
                    EV.PostWarningLog(module, $"Export recipe error:\r\n{ex}");
                    LOG.Error($"ProcessHistoryQuery:{ex}");
                    throw;
                }
                
            });
        }

        private static List<ProcessHistoryDeviceData> QueryExportProcessHistory(ProcessHistoryData processHistoryData,string module, List<ProcessDeviceItem> pmItemList)
        {
            var daySlices = DateRangeHelper.SplitInToHours(
                new DateRangeHelper(Convert.ToDateTime(processHistoryData.StepBeginTime),
                    Convert.ToDateTime(processHistoryData.StepEndTime)), 12);
            return GetProcessHistoryDeviceData(daySlices, module, pmItemList);
        }

        private static void SaveCsv(List<List<ProcessHistoryDeviceData>> phdd, RecipeProcessHistoryData recipeProcessHistoryData)
        {
            // 创建一个新的ExcelPackage实例
            using (ExcelPackage excelPackage = new ExcelPackage())
            {
                StringBuilder csvContent = new StringBuilder();

                csvContent.Append("Date,Time,Wafer,Step,StepName,");
                for (int i = 0; i < phdd[0].Count; i++)
                {
                    // 设置单元格的值为表头名
                    csvContent.Append($"{phdd[0][i].DeviceName}[{phdd[0][i].Unit}],");
                }

                csvContent.AppendLine(); // 换行

                foreach (var processDataList in phdd)//所有Step循环
                {
                    var stepDeviceData = processDataList
                        .Where(item => item.DeviceValue != null && item.DeviceValue.Count > 0)
                        .Select(item => item)
                        .FirstOrDefault(); // 如果没有找到，返回0

                    if (stepDeviceData == null)
                        continue;

                    // 遍历数组并写入 CSV 文件
                    for (int i = 0; i < stepDeviceData.DeviceValue.Count; i++)
                    {
                        var dateTime = new DateTime(long.Parse(stepDeviceData.TimeStamp[i]));
                        csvContent.Append(dateTime.ToString("yyyy-MM-dd") + ",");
                        csvContent.Append(dateTime.ToString("HH:mm:ss") + ",");
                        csvContent.Append(recipeProcessHistoryData.WaferInf + ",");
                        csvContent.Append(processDataList[0].StepNumber + ",");
                        csvContent.Append(processDataList[0].StepName + ",");

                        for (int j = 0; j < processDataList.Count; j++)
                        {
                            if (i < processDataList[j].DeviceValue.Count)

                                csvContent.Append(processDataList[j].DeviceValue[i].ToString("F3") + ",");
                            else
                                csvContent.Append("0,");
                        }
                        csvContent.AppendLine(); // 换行
                    }
                }

                // 保存Excel文件

                if (!Directory.Exists(_path))
                    Directory.CreateDirectory(_path);

                var filePath = $"{_path}\\{DateTime.Now:yyyy-MM-dd HH-mm-ss} - {recipeProcessHistoryData.Name}.csv";


                File.WriteAllText(filePath, csvContent.ToString());
            }
        }

        private static void SaveExcel(List<List<ProcessHistoryDeviceData>> phdd, RecipeProcessHistoryData recipeProcessHistoryData)
        {
            // 创建一个新的ExcelPackage实例
            using (ExcelPackage excelPackage = new ExcelPackage())
            {
                // 添加一个工作表
                ExcelWorksheet worksheet = excelPackage.Workbook.Worksheets.Add(recipeProcessHistoryData.Name);

                // 将数据写入Excel工作表
                worksheet.Cells[1, 1].Value = "Date";
                worksheet.Cells[1, 2].Value = "Time";
                worksheet.Cells[1, 3].Value = "Wafer";
                //worksheet.Cells[1, 4].Value = "Tray";
                worksheet.Cells[1, 4].Value = "Step";
                worksheet.Cells[1, 5].Value = "StepName";

                for (int i = 0; i < phdd[0].Count; i++)
                {
                    // 设置单元格的值为表头名
                    worksheet.Cells[1, i + 6].Value = $"{phdd[0][i].DeviceName}[{phdd[0][i].Unit}]";
                }

                int k = 1; //拼接Step换行用
                foreach (var processDataList in phdd) //所有Step循环
                {
                    for (int i = 0; i < processDataList.Count; i++) //单步Step循环
                    {
                        for (int j = 0; j < processDataList[i].DeviceValue.Count; j++) //当前Step，一个硬件产生的所有数据循环
                        {
                            if (i == 0) //i==0意味着数据属于同一个Step
                            {
                                //单步数据的共同数据，采集时间、Step序号和Step名称
                                var dateTime = new DateTime(long.Parse(processDataList[i].TimeStamp[j]));
                                worksheet.Cells[k + j + 1, 1].Value = dateTime.ToString("yyyy-MM-dd");
                                worksheet.Cells[k + j + 1, 2].Value = dateTime.ToString("HH:mm:ss");
                                worksheet.Cells[k + j + 1, 3].Value = recipeProcessHistoryData.WaferInf;
                                //worksheet.Cells[k + j + 1, 4].Value = RecipeProcessHistoryData.TrayInf;
                                worksheet.Cells[k + j + 1, 4].Value = processDataList[i].StepNumber;
                                worksheet.Cells[k + j + 1, 5].Value = processDataList[i].StepName;
                            }

                            //获取数据值
                            worksheet.Cells[k + j + 1, i + 6].Value = processDataList[i].DeviceValue[j];
                            worksheet.Cells[k + j + 1, i + 6].Style.Numberformat.Format = "0.000";
                        }
                    }

                    k += processDataList[0].DeviceValue.Count;
                }

                // 保存Excel文件

                if (!Directory.Exists(_path))
                    Directory.CreateDirectory(_path);

                FileInfo fileInfo = new FileInfo($"{_path}\\{DateTime.Now:yyyy-MM-dd HH-mm-ss} - {recipeProcessHistoryData.Name}.xlsx");

                // 设置所有单元格的水平和垂直对齐方式为居中
                worksheet.Cells.Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                worksheet.Cells.Style.VerticalAlignment = ExcelVerticalAlignment.Center;

                // 自适应所有列的宽度
                worksheet.Cells.AutoFitColumns();
                excelPackage.SaveAs(fileInfo);
            }
        }
    }
}