using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;

namespace MesWork.Pages
{
    /// <summary>
    /// 统计分析页面 — 残留量趋势分析 + 统计指标计算 + 明细数据
    /// 使用 GDI+ 绘制趋势折线图（含平均线 + 数据标签）
    /// </summary>
    public partial class UC_Statistics : UserControl
    {
        /// <summary>图表数据缓存</summary>
        private List<(DateTime time, double value, string label)> _chartData = new List<(DateTime, double, string)>();
        /// <summary>平均值（用于绘制参考线）</summary>
        private double _avgValue = 0;

        // ─── 配色常量 ───
        private static readonly Color CLR_PRIMARY = Color.FromArgb(74, 144, 217);
        private static readonly Color CLR_PRIMARY_DARK = Color.FromArgb(30, 58, 95);
        private static readonly Color CLR_AVG_LINE = Color.FromArgb(245, 158, 11);        // 橙色平均线
        private static readonly Color CLR_GRID = Color.FromArgb(236, 239, 243);
        private static readonly Color CLR_TEXT = Color.FromArgb(55, 65, 81);
        private static readonly Color CLR_TEXT_LIGHT = Color.FromArgb(107, 114, 128);
        private static readonly Color CLR_DOT_FILL = Color.FromArgb(74, 144, 217);
        private static readonly Color CLR_CARD_BG = Color.FromArgb(248, 250, 252);

        public UC_Statistics()
        {
            InitializeComponent();
            InitColumns();
            dtp_Start.Value = DateTime.Today.AddDays(-30);
            dtp_End.Value = DateTime.Today;
            // 订阅图表区域绘制
            pnl_Chart.Paint += pnl_Chart_Paint;
            pnl_Chart.Resize += (s, ev) => pnl_Chart.Invalidate();

            // 为筛选框加占位提示
            SetHint(txt_ModelNo, "机型号筛选...");
            SetHint(txt_OrderNo, "订货号筛选...");
        }

        private void SetHint(TextBox txt, string hint)
        {
            txt.Tag = hint;
            txt.Text = hint;
            txt.ForeColor = Color.FromArgb(156, 163, 175);
            txt.GotFocus += (s, e) => { if (txt.Text == hint) { txt.Text = ""; txt.ForeColor = CLR_PRIMARY_DARK; } };
            txt.LostFocus += (s, e) => { if (string.IsNullOrWhiteSpace(txt.Text)) { txt.Text = hint; txt.ForeColor = Color.FromArgb(156, 163, 175); } };
        }

        private string GetHintValue(TextBox txt)
        {
            return txt.Text == txt.Tag?.ToString() ? "" : txt.Text.Trim();
        }

        /// <summary>
        /// 预设明细表格列
        /// </summary>
        private void InitColumns()
        {
            dgv_Data.AutoGenerateColumns = false;
            dgv_Data.Columns.Clear();
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "序号", HeaderText = "序号", Width = 50, FillWeight = 30 });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "ID", HeaderText = "ID", DataPropertyName = "ID", Visible = false });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "测试时间", HeaderText = "检测时间", DataPropertyName = "测试时间", FillWeight = 100 });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "发动机号", HeaderText = "工件编号", DataPropertyName = "发动机号", FillWeight = 100 });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "订单号", HeaderText = "订货号", DataPropertyName = "订单号", FillWeight = 80 });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "机型号", HeaderText = "机型号", DataPropertyName = "机型号", FillWeight = 70 });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "残留量", HeaderText = "机油残留(mg)", DataPropertyName = "残留量", FillWeight = 80 });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "设备编号", HeaderText = "设备编号", DataPropertyName = "设备编号", FillWeight = 60 });
            dgv_Data.Columns.Add(new DataGridViewTextBoxColumn { Name = "操作员", HeaderText = "操作员", DataPropertyName = "操作员", FillWeight = 60 });
        }

        /// <summary>
        /// 统计分析按钮
        /// </summary>
        private void btn_Analyze_Click(object sender, EventArgs e)
        {
            try
            {
                var pageCountParam = new SqlParameter("@PageCount", SqlDbType.Int) { Direction = ParameterDirection.Output };
                var itemCountParam = new SqlParameter("@ItemCount", SqlDbType.Int) { Direction = ParameterDirection.Output };
                var parms = new SqlParameter[]
                {
                    new SqlParameter("@发动机号", ""),
                    new SqlParameter("@机型号", GetHintValue(txt_ModelNo)),
                    new SqlParameter("@工单号", GetHintValue(txt_OrderNo)),
                    new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
                    new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
                    new SqlParameter("@PageCurrent", 1),
                    new SqlParameter("@PageSize", 9999),
                    pageCountParam,
                    itemCountParam
                };
                SqlOperation.ExecuteStoredProcedure("称重记录_分页查询", parms, out DataTable dt, out string err);

                if (dt != null && dt.Rows.Count > 0)
                {
                    dgv_Data.DataSource = dt;
                    FillRowNumbers();
                    CalculateStatistics(dt);
                    BuildChartData(dt);
                    pnl_Chart.Invalidate();
                }
                else
                {
                    _chartData.Clear();
                    ClearStatLabels();
                    pnl_Chart.Invalidate();
                    MessageBox.Show("查询范围内无数据", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show($"查询失败：{ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 填充表格序号列（与图表数据点编号对应）
        /// 图表按时间升序排列，表格按ID降序，序号在数据排序后重新映射
        /// </summary>
        private void FillRowNumbers()
        {
            // 表格数据按ID降序排列（最新在前），序号直接按行号赋值
            for (int i = 0; i < dgv_Data.Rows.Count; i++)
            {
                dgv_Data.Rows[i].Cells["序号"].Value = i + 1;
            }
        }

        /// <summary>
        /// 从DataTable构建图表数据（确保所有行都被处理）
        /// </summary>
        private void BuildChartData(DataTable dt)
        {
            _chartData.Clear();
            // 查找时间列和数值列
            string timeCol = dt.Columns.Contains("进站时间") ? "进站时间" :
                             dt.Columns.Contains("测试时间") ? "测试时间" : null;
            string valCol = dt.Columns.Contains("残油量") ? "残油量" :
                            dt.Columns.Contains("残留量") ? "残留量" :
                            dt.Columns.Contains("放油量") ? "放油量" : null;
            string labelCol = dt.Columns.Contains("发动机号") ? "发动机号" : null;

            if (timeCol == null || valCol == null) return;

            foreach (DataRow row in dt.Rows)
            {
                DateTime t;
                double v;
                string lbl = labelCol != null ? row[labelCol]?.ToString() ?? "" : "";

                // 时间解析：如果失败则使用当前时间递增
                if (!DateTime.TryParse(row[timeCol]?.ToString(), out t))
                    t = DateTime.Now;

                // 数值解析：如果失败或为空，默认为0（也是有效数据点）
                object rawVal = row[valCol];
                if (rawVal == null || rawVal == DBNull.Value || !double.TryParse(rawVal.ToString(), out v))
                    v = 0;

                _chartData.Add((t, v, lbl));
            }
            // 不排序，保持DataTable原始行顺序（与表格序号一致）
        }

        /// <summary>
        /// GDI+ 绘制折线图（增强版）
        /// </summary>
        private void pnl_Chart_Paint(object sender, PaintEventArgs e)
        {
            var g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

            var rect = pnl_Chart.ClientRectangle;
            int padL = 80, padR = 40, padT = 50, padB = 60;
            int chartW = rect.Width - padL - padR;
            int chartH = rect.Height - padT - padB;

            if (chartW < 50 || chartH < 50) return;

            // 绘制背景
            using (var bgBrush = new SolidBrush(Color.White))
                g.FillRectangle(bgBrush, rect);

            // 空数据提示
            if (_chartData.Count == 0)
            {
                using (var font = new Font("微软雅黑", 14F))
                using (var brush = new SolidBrush(Color.FromArgb(156, 163, 175)))
                {
                    var msg = "📊 设置筛选条件后点击「统计分析」查看趋势图";
                    var sz = g.MeasureString(msg, font);
                    g.DrawString(msg, font, brush, (rect.Width - sz.Width) / 2, (rect.Height - sz.Height) / 2);
                }
                return;
            }

            // 计算数据范围
            double minVal = _chartData.Min(d => d.value);
            double maxVal = _chartData.Max(d => d.value);
            double range = maxVal - minVal;
            if (range < 0.001) { range = Math.Max(Math.Abs(maxVal) * 0.2, 1); }
            minVal -= range * 0.12;
            maxVal += range * 0.12;
            if (minVal < 0 && _chartData.Min(d => d.value) >= 0) minVal = 0; // 不让Y轴负数（如果原始数据非负）

            int totalPts = _chartData.Count;

            // ─── 绘制网格线和Y轴标签 ───
            using (var gridPen = new Pen(CLR_GRID, 1) { DashStyle = DashStyle.Dot })
            using (var axisFont = new Font("微软雅黑", 9F))
            using (var axisBrush = new SolidBrush(CLR_TEXT_LIGHT))
            using (var axisPen = new Pen(Color.FromArgb(200, 210, 220), 1))
            {
                // Y轴线
                g.DrawLine(axisPen, padL, padT, padL, padT + chartH);
                // X轴线
                g.DrawLine(axisPen, padL, padT + chartH, padL + chartW, padT + chartH);

                for (int i = 0; i <= 5; i++)
                {
                    int y = padT + chartH - (int)(chartH * i / 5.0);
                    if (i > 0) g.DrawLine(gridPen, padL + 1, y, padL + chartW, y);
                    double val = minVal + (maxVal - minVal) * i / 5.0;
                    string valStr = val.ToString("F2");
                    var sz = g.MeasureString(valStr, axisFont);
                    g.DrawString(valStr, axisFont, axisBrush, padL - sz.Width - 6, y - sz.Height / 2);
                }

                // X轴标签 — 序号均匀排布（1, 2, 3...）
                // 计算合适的标签间隔，避免过于密集
                int maxLabels = Math.Max(1, chartW / 40); // 每个标签至少40px空间
                int labelStep = Math.Max(1, (totalPts - 1) / Math.Max(maxLabels - 1, 1));
                // 如果数据点少于maxLabels，每个都显示
                if (totalPts <= maxLabels) labelStep = 1;

                for (int i = 0; i < totalPts; i += labelStep)
                {
                    float xPos = totalPts == 1 ? padL + chartW / 2f
                        : padL + (float)chartW * i / (totalPts - 1);
                    string label = (i + 1).ToString();
                    var sz = g.MeasureString(label, axisFont);
                    g.DrawString(label, axisFont, axisBrush, xPos - sz.Width / 2, padT + chartH + 8);
                    g.DrawLine(axisPen, (int)xPos, padT + chartH, (int)xPos, padT + chartH + 5);
                }
                // 确保最后一个序号显示
                if (totalPts > 1 && (totalPts - 1) % labelStep != 0)
                {
                    float lastX = padL + chartW;
                    string lastLabel = totalPts.ToString();
                    var lastSz = g.MeasureString(lastLabel, axisFont);
                    g.DrawString(lastLabel, axisFont, axisBrush, lastX - lastSz.Width / 2, padT + chartH + 8);
                    g.DrawLine(axisPen, (int)lastX, padT + chartH, (int)lastX, padT + chartH + 5);
                }
            }

            // ─── 计算所有数据点坐标（X轴按序号均匀排布）───
            var points = new PointF[totalPts];
            for (int i = 0; i < totalPts; i++)
            {
                float x = totalPts == 1 ? padL + chartW / 2f
                    : padL + (float)chartW * i / (totalPts - 1);
                float y = padT + chartH - (float)(chartH * ((_chartData[i].value - minVal) / (maxVal - minVal)));
                points[i] = new PointF(x, y);
            }

            // ─── 渐变填充区域 ───
            if (points.Length >= 2)
            {
                using (var fillPath = new GraphicsPath())
                {
                    fillPath.AddLines(points);
                    fillPath.AddLine(points.Last(), new PointF(points.Last().X, padT + chartH));
                    fillPath.AddLine(new PointF(points.Last().X, padT + chartH), new PointF(points.First().X, padT + chartH));
                    fillPath.CloseFigure();
                    using (var fillBrush = new LinearGradientBrush(
                        new Point(0, padT), new Point(0, padT + chartH),
                        Color.FromArgb(50, 74, 144, 217), Color.FromArgb(3, 74, 144, 217)))
                    {
                        g.FillPath(fillBrush, fillPath);
                    }
                }

                // 折线（粗线+阴影效果）
                using (var shadowPen = new Pen(Color.FromArgb(30, 74, 144, 217), 5f))
                {
                    shadowPen.LineJoin = LineJoin.Round;
                    g.DrawLines(shadowPen, points);
                }
                using (var linePen = new Pen(CLR_PRIMARY, 2.5f))
                {
                    linePen.LineJoin = LineJoin.Round;
                    g.DrawLines(linePen, points);
                }
            }

            // ─── 平均线（红色虚线 + 箭头 + 标签）───
            if (_chartData.Count > 0)
            {
                float avgY = padT + chartH - (float)(chartH * ((_avgValue - minVal) / (maxVal - minVal)));
                if (avgY >= padT && avgY <= padT + chartH)
                {
                    using (var avgPen = new Pen(CLR_AVG_LINE, 1.8f) { DashStyle = DashStyle.Dash })
                    {
                        g.DrawLine(avgPen, padL, avgY, padL + chartW, avgY);
                    }
                    // 平均线标签（右侧带箭头标识）
                    using (var avgFont = new Font("微软雅黑", 9F, FontStyle.Bold))
                    using (var avgBrush = new SolidBrush(CLR_AVG_LINE))
                    {
                        string avgText = $"▶ 平均 {_avgValue:F2}";
                        var sz = g.MeasureString(avgText, avgFont);
                        // 背景
                        float lblX = padL + chartW - sz.Width - 4;
                        float lblY = avgY - sz.Height - 3;
                        using (var bgBrush = new SolidBrush(Color.FromArgb(220, 255, 255, 255)))
                            g.FillRectangle(bgBrush, lblX - 3, lblY, sz.Width + 6, sz.Height + 2);
                        g.DrawString(avgText, avgFont, avgBrush, lblX, lblY);
                        // 小三角箭头指向线
                        var arrowPts = new PointF[] {
                            new PointF(padL + chartW + 2, avgY),
                            new PointF(padL + chartW + 10, avgY - 5),
                            new PointF(padL + chartW + 10, avgY + 5)
                        };
                        g.FillPolygon(avgBrush, arrowPts);
                    }
                }
            }

            // ─── 数据点（带光晕效果）───
            for (int i = 0; i < points.Length; i++)
            {
                var pt = points[i];
                // 光晕
                using (var glowBrush = new SolidBrush(Color.FromArgb(40, 74, 144, 217)))
                    g.FillEllipse(glowBrush, pt.X - 8, pt.Y - 8, 16, 16);
                // 白色底
                g.FillEllipse(Brushes.White, pt.X - 5, pt.Y - 5, 10, 10);
                // 蓝色圆点
                using (var dotBrush = new SolidBrush(CLR_DOT_FILL))
                    g.FillEllipse(dotBrush, pt.X - 4, pt.Y - 4, 8, 8);
                // 数值标签（只有当数据点不太密时显示）
                if (_chartData.Count <= 15)
                {
                    using (var valFont = new Font("微软雅黑", 8F))
                    using (var valBrush = new SolidBrush(CLR_PRIMARY_DARK))
                    {
                        string valText = _chartData[i].value.ToString("F1");
                        var sz = g.MeasureString(valText, valFont);
                        g.DrawString(valText, valFont, valBrush, pt.X - sz.Width / 2, pt.Y - sz.Height - 6);
                    }
                }
            }

            // ─── 图表右下角水印 ───
            using (var wmFont = new Font("微软雅黑", 8F))
            using (var wmBrush = new SolidBrush(Color.FromArgb(80, 156, 163, 175)))
            {
                string wm = $"共 {_chartData.Count} 个样本";
                var sz = g.MeasureString(wm, wmFont);
                g.DrawString(wm, wmFont, wmBrush, padL + chartW - sz.Width, padT + 4);
            }
        }

        /// <summary>
        /// 计算统计指标（基于残留量列）
        /// </summary>
        private void CalculateStatistics(DataTable dt)
        {
            var values = new List<double>();
            string colName = dt.Columns.Contains("残油量") ? "残油量" :
                             dt.Columns.Contains("残留量") ? "残留量" : null;
            if (colName == null)
            {
                foreach (DataColumn col in dt.Columns)
                {
                    if (col.ColumnName.Contains("残留") || col.ColumnName.Contains("残油") || col.ColumnName.Contains("重量"))
                    {
                        colName = col.ColumnName;
                        break;
                    }
                }
            }

            if (colName != null)
            {
                foreach (DataRow row in dt.Rows)
                {
                    object rawVal = row[colName];
                    if (rawVal != null && rawVal != DBNull.Value && double.TryParse(rawVal.ToString(), out double v))
                        values.Add(v);
                    else
                        values.Add(0); // 空值也算0，确保样本数一致
                }
            }

            if (values.Count == 0)
            {
                ClearStatLabels();
                return;
            }

            values.Sort();
            double max = values.Max();
            double min = values.Min();
            double avg = values.Average();
            _avgValue = avg; // 保存平均值用于绘图
            double median = values.Count % 2 == 0
                ? (values[values.Count / 2 - 1] + values[values.Count / 2]) / 2.0
                : values[values.Count / 2];
            double rangeVal = max - min;
            double variance = values.Sum(v => Math.Pow(v - avg, 2)) / values.Count;
            double stdDev = Math.Sqrt(variance);

            // 更新统计指标标签
            lbl_StatMax.Text      = $"最大值  {max:F4}";
            lbl_StatMin.Text      = $"最小值  {min:F4}";
            lbl_StatAvg.Text      = $"平均值  {avg:F4}";
            lbl_StatMedian.Text   = $"中位数  {median:F4}";
            lbl_StatRange.Text    = $"极差    {rangeVal:F4}";
            lbl_StatVariance.Text = $"方差    {variance:F4}";
            lbl_StatStdDev.Text   = $"标准差  {stdDev:F4}";
            lbl_StatCount.Text    = $"样本数  {values.Count}";
        }

        private void ClearStatLabels()
        {
            lbl_StatMax.Text = "最大值  —";
            lbl_StatMin.Text = "最小值  —";
            lbl_StatAvg.Text = "平均值  —";
            lbl_StatMedian.Text = "中位数  —";
            lbl_StatRange.Text = "极差    —";
            lbl_StatVariance.Text = "方差    —";
            lbl_StatStdDev.Text = "标准差  —";
            lbl_StatCount.Text = "样本数  0";
        }

        /// <summary>
        /// 导出数据
        /// </summary>
        private void btn_Export_Click(object sender, EventArgs e)
        {
            CrudHelper.ExportToExcel("统计分析", "统计分析", () =>
            {
                var (pageCountParam, itemCountParam) = PagerBar.CreateOutputParams();
                var parms = new SqlParameter[]
                {
                    new SqlParameter("@发动机号", ""),
                    new SqlParameter("@机型号", GetHintValue(txt_ModelNo)),
                    new SqlParameter("@工单号", GetHintValue(txt_OrderNo)),
                    new SqlParameter("@开始时间", dtp_Start.Value.ToString("yyyy-MM-dd")),
                    new SqlParameter("@结束时间", dtp_End.Value.AddDays(1).ToString("yyyy-MM-dd")),
                    new SqlParameter("@PageCurrent", 1),
                    new SqlParameter("@PageSize", 9999999),
                    pageCountParam, itemCountParam
                };
                SqlOperation.ExecuteStoredProcedure("称重记录_分页查询", parms, out DataTable dt, out string err);
                return dt;
            }, dgv_Data.Rows.Count > 0);
        }
    }
}
