using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static CowainHmi.LogSearch;
using System.IO;
using System.Runtime.InteropServices;
using PCHMI;
using static System.Windows.Forms.VisualStyles.VisualStyleElement.ProgressBar;
using System.Data.OleDb;
using CowainHmi.ProductionQty;
using System.Drawing.Design;
using System.Threading;

namespace CowainHmi
{
    public partial class ProductionDisplay : UserControl
    {
        public ProductionDisplay()
        {
            InitializeComponent();
        }
        [Category("PCHMI"), Description("PLC编号")]
        public int PLCId
        {
            get;
            set;
        }
        // 定义并添加自定义属性  
        [Browsable(true)]
        [Category("Custom Properties")]
        [Description("产量文件路径")]
        public string ProductionFolderPath
        {
            get;
            set;
        }
        [Browsable(true)]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("Custom Properties")]
        [Description("班别A开始时间")]
        public string ShiftAStartAddress
        {
            get;
            set;
        }
        [Browsable(true)]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("Custom Properties")]
        [Description("班别A结束时间")]
        public string ShiftAEndAddress
        {
            get;
            set;
        }
        [Browsable(true)]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("Custom Properties")]
        [Description("班别B开始时间")]
        public string ShiftBStartAddress
        {
            get;
            set;
        }
        [Browsable(true)]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("Custom Properties")]
        [Description("班别B结束时间")]
        public string ShiftBEndAddress
        {
            get;
            set;
        }
        [Browsable(true)]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("Custom Properties")]
        [Description("班别C开始时间")]
        public string ShiftCStartAddress
        {
            get;
            set;
        }
        [Browsable(true)]
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("Custom Properties")]
        [Description("班别C结束时间")]
        public string ShiftCEndAddress
        {
            get;
            set;
        }
        [Category("PCHMI"), Description("工站名称")]
        public string StationName { get; set; }
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("PCHMI"), Description("上传命令地址")]
        public string UpCmdAddr { get; set; }
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("PCHMI"), Description("上传命令计数地址")]

        public string RetCmdAddr { get; set; }
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("PCHMI"), Description("反馈命令计数地址")]
        public string RetCountAddr { get; set; }
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("PCHMI"), Description("上传工单地址")]
        public string UpOrderAddr { get; set; }
        [Editor(typeof(StringText), typeof(UITypeEditor))]
        [Category("PCHMI"), Description("上传部件号地址")]
        public string UpPartNumAddr { get; set; }
        private void SetCombox()
        {
            string text = System.Windows.Forms.Application.StartupPath + @"\" + ProductionFolderPath;
            if (!Directory.Exists(text) && text.Length > 0)
            {
                Directory.CreateDirectory(text);
            }
            string productionFile = text + @"\" + dateTimePicker1.Value.ToString("yyMMdd") + ".csv";
            List<生产数据> productionData = ReadProductionData(productionFile);
            //PartNum下拉框获取唯一的零部件编号
            if (productionData.Count == 0)
            {
                partNum.DataSource = null;
                return;
            }
            var listDown = (from item in productionData
                            where !string.IsNullOrWhiteSpace(item.零部件)
                            select item.零部件).Distinct().ToList();
            listDown.Insert(0, "全部");
            partNum.DataSource = listDown;
        }

        private void button1_Click(object sender, EventArgs e)
        {

            CalcProductionQty();
        }
        private void CalcProductionQty()
        {
            string text = System.Windows.Forms.Application.StartupPath + @"\" + ProductionFolderPath;
            if (!Directory.Exists(text) && text.Length > 0)
            {
                Directory.CreateDirectory(text);
            }
            string productionFile = text + @"\" + dateTimePicker1.Value.ToString("yyMMdd") + ".csv";
            List<生产数据> productionData = ReadProductionData(productionFile);
            List<Hours> hoursList = new List<Hours>();

            for (int i = 0; i < shiftTime.Count; i++)
            {
                var item = shiftTime[i];
                DateTime shiftStartTime = item.开始时间;

                while (shiftStartTime < item.结束时间)
                {
                    DateTime nextShiftStartTime = item.结束时间;

                    // Check if there is a next shift
                    if (i + 1 < shiftTime.Count)
                    {
                        nextShiftStartTime = shiftTime[i + 1].开始时间;
                    }

                    DateTime endTime = shiftStartTime.AddHours(1);

                    // Adjust the end time if it overlaps with the next shift
                    if (endTime > nextShiftStartTime)
                    {
                        endTime = nextShiftStartTime;
                    }

                    Hours hours1 = new Hours()
                    {
                        开始时间 = shiftStartTime,
                        结束时间 = endTime,
                        班别 = item.班别,
                    };
                    hoursList.Add(hours1);

                    shiftStartTime = endTime;
                }
            }

            List<单班产量> shift = new List<单班产量>();
            string partFilter = partNum.Text == "全部" ? "" : partNum.Text;
            foreach (var item in hoursList)
            {
                var info = productionData
                    .Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间
                          && (partFilter == "" || pd.零部件 == partFilter));
                单班产量 production = new 单班产量()
                {
                    时间 = item.开始时间,
                    工单 = info.Any() ? info.FirstOrDefault().工单 : "",
                    零部件 = info.Any() ? info.FirstOrDefault().零部件 : "",
                    班别 = item.班别,
                    产量 = info.Any() ? info.Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间).Count() : 0,
                    合格 = info.Any() ? info.Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间 && pd.合格否 == 1).Count() : 0,
                    不合格 = info.Any() ? info.Where(pd => pd.时间 >= item.开始时间 && pd.时间 < item.结束时间 && pd.合格否 == 2).Count() : 0,
                };
                shift.Add(production);
            };

            dataGridView1.DataSource = shift;

            //统计按班别的总产量，总合格，总不合格
            var shiftSum = (from item in shift
                            group item by item.班别 into g
                            select new 单班产量
                            {
                                班别 = g.Key,
                                产量 = g.Sum(x => x.产量),
                                合格 = g.Sum(x => x.合格),//合格=1，则直接对1求和
                                不合格 = g.Sum(x => x.不合格)//不合格=2，则对2-1求和
                            }).ToList();
            var shiftASum = shiftSum.FirstOrDefault(x => x.班别 == "A");
            var shiftBSum = shiftSum.FirstOrDefault(x => x.班别 == "B");
            var shiftCSum = shiftSum.FirstOrDefault(x => x.班别 == "C");
            totalA.Text = shiftASum.产量.ToString();
            totalB.Text = shiftBSum.产量.ToString();
            totalC.Text = shiftCSum.产量.ToString();
            OK_A.Text = shiftASum.合格.ToString();
            OK_B.Text = shiftBSum.合格.ToString();
            OK_C.Text = shiftCSum.合格.ToString();
            NG_A.Text = shiftASum.不合格.ToString();
            NG_B.Text = shiftBSum.不合格.ToString();
            NG_C.Text = shiftCSum.不合格.ToString();
        }
        public bool IsWithinShiftTime(int hour, double startTime, double endTime)
        {
            if (startTime < endTime)
            {
                // 普通时间段
                return hour >= startTime && hour < endTime;
            }
            else
            {
                // 跨越午夜的时间段
                return hour >= startTime || hour < endTime;
            }
        }
        private List<生产数据> ReadProductionData(string filePath)
        {
            var productionData = new List<生产数据>();

            if (!File.Exists(filePath))
            {
                return productionData;
            }

            int N = 1;
            foreach (var line in File.ReadAllLines(filePath, Encoding.GetEncoding("GB2312")))
            {
                try
                {
                    if (N == 1)
                    {
                        N++;
                        continue;
                    }
                    var parts = line.Split(',');
                    var time = DateTime.ParseExact(parts[0].Trim(), "yyyy/MM/dd HH:mm:ss", CultureInfo.InvariantCulture);

                    productionData.Add(new 生产数据
                    {
                        时间 = time,
                        工单 = parts[1],
                        零部件 = parts[2],
                        合格否 = int.Parse(parts[3])
                    }
                    );
                }
                catch (Exception ex)
                {

                    //throw;
                }
                N++;
            }

            return productionData;
        }
        public class 班别时间
        {
            public string 班别 { get; set; }
            public DateTime 开始时间 { get; set; }
            public DateTime 结束时间 { get; set; }
        }
        public class Hours
        {
            public string 班别 { get; set; }
            public DateTime 开始时间 { get; set; }
            public DateTime 结束时间 { get; set; }
        }
        public class 单班产量
        {
            public DateTime 时间 { get; set; }
            public string 工单 { get; set; }
            public string 零部件 { get; set; }
            public string 班别 { get; set; }
            public int 产量 { get; set; }
            public int 合格 { get; set; }
            public int 不合格 { get; set; }
            public int SortOrder { get; set; } // 新增排序字段
        }

        public class 生产数据
        {
            public DateTime 时间 { get; set; }
            public string 工单 { get; set; }
            public string 零部件 { get; set; }
            public int 合格否 { get; set; }
        }
        static string ConvertTimeToFormattedString(string timeString)
        {
            if (string.IsNullOrWhiteSpace(timeString) || timeString.Length != 4)
            {
                throw new ArgumentException("Invalid time format. Please use 'HHmm' format.");
            }

            // 提取小时和分钟  
            int hour = int.Parse(timeString.Substring(0, 2));
            int minute = int.Parse(timeString.Substring(2, 2));

            // 创建TimeSpan对象  
            TimeSpan timeSpan = new TimeSpan(hour, minute, 0);

            // 将TimeSpan转换为字符串  
            return timeSpan.ToString("hh\\:mm\\:ss");
        }
        public class CalcStartEndTime
        {
            public DateTime StartTime { get; set; }
            public DateTime EndTime { get; set; }
        }
        private CalcStartEndTime GetDateTime(string startTimeChar, string endTimeChar, DateTime queryDateTime)
        {
            CalcStartEndTime calcStartEndTime = new CalcStartEndTime();
            int startTime = int.Parse(startTimeChar.Substring(0, 2));
            int endTime = int.Parse(endTimeChar.Substring(0, 2));

            DateTime startDateTime;
            DateTime endDateTime;

            // Determine the start and end dates
            if (startTime > endTime)
            {
                startDateTime = queryDateTime;
                endDateTime = queryDateTime.AddDays(1);
            }
            else
            {
                if (startTime < 9 && endTime < 9)
                {
                    startDateTime = queryDateTime.AddDays(1);
                    endDateTime = queryDateTime.AddDays(1);
                }
                else
                {
                    startDateTime = queryDateTime;
                    endDateTime = queryDateTime;
                }
            }

            // Parse the exact times
            calcStartEndTime.StartTime = DateTime.ParseExact(startDateTime.ToString("yyyy-MM-dd ") + ConvertTimeToFormattedString(startTimeChar), "yyyy-MM-dd HH:mm:ss", null);
            calcStartEndTime.EndTime = DateTime.ParseExact(endDateTime.ToString("yyyy-MM-dd ") + ConvertTimeToFormattedString(endTimeChar), "yyyy-MM-dd HH:mm:ss", null);

            return calcStartEndTime;
        }
        private void SetShiftTime()
        {
            ReadShiftTime();
            var shiftATime = GetDateTime(shiftTimePLC[0], shiftTimePLC[1], dateTimePicker1.Value);
            var shiftBTime = GetDateTime(shiftTimePLC[2], shiftTimePLC[3], dateTimePicker1.Value);
            var shiftCTime = GetDateTime(shiftTimePLC[4], shiftTimePLC[5], dateTimePicker1.Value);
            shiftTime = new List<班别时间>()
            {
                   new 班别时间 { 班别="A",开始时间 = shiftATime.StartTime, 结束时间 = shiftATime.EndTime },
                   new 班别时间 { 班别="B",开始时间 = shiftBTime.StartTime, 结束时间 = shiftBTime.EndTime },
                   new 班别时间 { 班别="C",开始时间 = shiftCTime.StartTime, 结束时间 = shiftCTime.EndTime }
            };
        }

        private List<string> shiftTimePLC = new List<string>();
        private void ReadShiftTime()
        {
            if (!PClass.SystemRun)
            {
                return;
            }
            shiftTimePLC.Clear();
            List<string> shiftTimeDuration = new List<string>()
            {
                 PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAStartAddress,4),
                 PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAEndAddress,4),
                 PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBStartAddress, 4),
                 PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBEndAddress, 4),
                 PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCStartAddress, 4),
                 PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCEndAddress, 4),
            };
            foreach (var item in shiftTimeDuration)
            {
                if (!string.IsNullOrEmpty(item))
                {
                    shiftTimePLC.Add(item);
                }
            }
            if (shiftTimePLC.Count != 6)
            {
                shiftTimePLC.Clear();
                shiftTimePLC.Add("0830");
                shiftTimePLC.Add("1630");
                shiftTimePLC.Add("1700");
                shiftTimePLC.Add("0130");
                shiftTimePLC.Add("0130");
                shiftTimePLC.Add("0830");
            }
        }

        /// <summary>
        /// 根据当前时间，获取存储的文件名
        /// </summary>
        private string GetFileName()
        {
            var dateTime = DateTime.Now;
            var shiftATime = GetDateTime(shiftTimePLC[0], shiftTimePLC[1], dateTime.AddDays(-1));
            var shiftBTime = GetDateTime(shiftTimePLC[2], shiftTimePLC[3], dateTime.AddDays(-1));
            var shiftCTime = GetDateTime(shiftTimePLC[4], shiftTimePLC[5], dateTime.AddDays(-1));
            List<班别时间> shiftTimeLastDay = new List<班别时间>()
            {
                   new 班别时间 { 班别="A",开始时间 = shiftATime.StartTime, 结束时间 = shiftATime.EndTime },
                   new 班别时间 { 班别="B",开始时间 = shiftBTime.StartTime, 结束时间 = shiftBTime.EndTime },
                   new 班别时间 { 班别="C",开始时间 = shiftCTime.StartTime, 结束时间 = shiftCTime.EndTime }
            };
            var shiftDuration = shiftTimeLastDay.Where(item => item.开始时间 <= dateTime && dateTime < item.结束时间);
            if (shiftDuration.Any())
            {
                return shiftTimeLastDay[0].开始时间.ToString("yyMMdd");
            }
            return dateTime.ToString("yyMMdd");
        }
        private List<班别时间> shiftTime;
        private async void ProductionDisplay_Load(object sender, EventArgs e)
        {
            if (!PClass.SystemRun)
            {
                return;
            }
            PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAStartAddress, 4);
            PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftAEndAddress, 4);
            PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBStartAddress, 4);
            PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftBEndAddress, 4);
            PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCStartAddress, 4);
            PCHMI.VL.GET_SIEMENS_STRING(PLCId, ShiftCEndAddress, 4);
            PCHMI.RT.GET_INT16s(PLCId, UpCmdAddr, 6);
            PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpOrderAddr, 30);
            PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpPartNumAddr, 50);
            await Task.Delay(300);
            SetShiftTime();
            dataGridView1.AutoGenerateColumns = false;
            SetCombox();
            ReadShiftTime();
            this.timer1.Enabled = true;
        }

        private void dateTimePicker1_ValueChanged(object sender, EventArgs e)
        {
            SetShiftTime();
        }
        private short retCountSave;
        private void timer1_Tick(object sender, EventArgs e)
        {
            if (PClass.IsPlcLink(PLCId) && !string.IsNullOrEmpty(UpCmdAddr))
            {
                var ar = PCHMI.RT.GET_INT16s(PLCId, UpCmdAddr, 6);
                var order = PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpOrderAddr, 30);
                var partNum = PCHMI.RT.GET_SIEMENS_STRING(PLCId, UpPartNumAddr, 50);
                if (ar[0] == 1 && retCountSave != ar[1])
                {
                    //PLC触发产量上传
                    string fileName = GetFileName();
                    string stName = string.Empty;
                    if (string.IsNullOrEmpty(StationName))
                    {
                        stName = this.Name;
                    }
                    else
                    {
                        stName = StationName;
                    }
                    SaveData(stName, fileName, order, partNum, ar[5]);
                    PCHMI.RT.SEND_INT16(PLCId, RetCmdAddr, 1);
                    PCHMI.RT.SEND_INT16(PLCId, RetCountAddr, ar[1]);
                    retCountSave = ar[1];

                }

            }
        }



        public void SaveData(string stationName, string fileName, string order, string partNum, short isPass)
        {
            if (PClass.SystemRun)
            {
                string text = System.Windows.Forms.Application.StartupPath + @"\" + ProductionFolderPath;
                if (!Directory.Exists(text) && text.Length > 0)
                {
                    Directory.CreateDirectory(text);
                }
                string productionFile = text + @"\" + fileName + ".csv";
                if (!File.Exists(productionFile))
                {
                    CsvHelper.CreateCsv(productionFile, new string[]
                        {
                        "时间",
                        "工单",
                        "零部件",
                        "合格否"
                        });
                }
                CsvHelper.WriteLine(productionFile, new List<string>() { DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss"), order, partNum, isPass.ToString() });
            }

        }

        private void btnTimeEdit_Click(object sender, EventArgs e)
        {
            List<string> strings = new List<string>() { ShiftAStartAddress, ShiftAEndAddress, ShiftBStartAddress, ShiftBEndAddress, ShiftCStartAddress, ShiftCEndAddress };
            DlgProductionTimeEdit dlg = new DlgProductionTimeEdit(PLCId, strings);
            var result = dlg.ShowDialog();
            if (result == DialogResult.OK)
            {
                SetShiftTime();
                ReadShiftTime();
            }
        }

        private void partNum_MouseDown(object sender, MouseEventArgs e)
        {
            SetCombox();
        }
    }
}
