using System;
using System.Collections.Generic;
using Dapper;
using MySqlConnector;
using CncModels.Entity;
using CncModels.Enum;
using log4net;

namespace CncCollector.Core
{
    /// <summary>
    /// 日终汇总作业。
    /// 在配置的时间（默认01:00）执行，结账所有活跃段，汇总日产量数据。
    /// </summary>
    public class DailySummaryJob
    {
        private static readonly ILog _log = LogManager.GetLogger(typeof(DailySummaryJob));

        private readonly string _businessConnStr;

        /// <summary>
        /// 初始化日终汇总作业
        /// </summary>
        /// <param name="businessConnStr">业务库连接字符串</param>
        public DailySummaryJob(string businessConnStr)
        {
            _businessConnStr = businessConnStr;
        }

        /// <summary>
        /// 执行日终汇总，汇总指定日期的产量数据
        /// </summary>
        /// <param name="summaryDate">要汇总的日期（通常为昨天）</param>
        /// <returns>true=汇总成功，false=汇总失败（可重试）</returns>
        public bool Execute(DateTime summaryDate)
        {
            _log.Info($"========== 日终汇总开始（日期={summaryDate:yyyy-MM-dd}） ==========");
            var sw = System.Diagnostics.Stopwatch.StartNew();

            try
            {
                using (var conn = new MySqlConnection(_businessConnStr))
                {
                    conn.Open();
                    using (var tran = conn.BeginTransaction())
                    {
                        try
                        {
                            // 1. 结账所有活跃段（end_of_day）
                            conn.Execute(@"UPDATE cnc_production_segment 
                                SET end_time = COALESCE(end_time, NOW()), 
                                    close_reason = @Reason, is_settled = 1, updated_at = NOW()
                                WHERE is_settled = 0 AND DATE(start_time) <= @Date",
                                new { Reason = SegmentCloseReason.EndOfDay, Date = summaryDate }, tran);

                            // 2. 为 quantity 为 NULL 的段计算产量
                            conn.Execute(@"UPDATE cnc_production_segment 
                                SET quantity = GREATEST(0, COALESCE(end_part_count, 0) - start_part_count)
                                WHERE quantity IS NULL AND is_settled = 1 AND DATE(start_time) <= @Date",
                                new { Date = summaryDate }, tran);

                            // 3. 按 (machine_id, production_date, program_name) 汇总到 cnc_daily_production
                            // 先删除旧汇总（幂等）
                            conn.Execute(@"DELETE FROM cnc_daily_production WHERE production_date = @Date",
                                new { Date = summaryDate }, tran);

                            // 插入新汇总
                            conn.Execute(@"INSERT INTO cnc_daily_production (machine_id, production_date, program_name, total_quantity, segment_count, total_run_time, total_cutting_time, total_cycle_time, created_at, updated_at)
                                SELECT machine_id, @Date, program_name, 
                                    SUM(COALESCE(quantity, 0)), 
                                    COUNT(*), 
                                    NULL, NULL, NULL,
                                    NOW(), NOW()
                                FROM cnc_production_segment 
                                WHERE DATE(start_time) = @Date AND is_settled = 1
                                GROUP BY machine_id, program_name",
                                new { Date = summaryDate }, tran);

                            // 4. 汇总到 cnc_worker_daily_summary（通过绑定关系）
                            conn.Execute(@"DELETE FROM cnc_worker_daily_summary WHERE production_date = @Date",
                                new { Date = summaryDate }, tran);

                            conn.Execute(@"INSERT INTO cnc_worker_daily_summary (worker_id, production_date, total_quantity, machine_count, program_count, created_at, updated_at)
                                SELECT wm.worker_id, @Date, 
                                    SUM(dp.total_quantity), 
                                    COUNT(DISTINCT dp.machine_id), 
                                    COUNT(DISTINCT dp.program_name),
                                    NOW(), NOW()
                                FROM cnc_daily_production dp
                                INNER JOIN cnc_worker_machine wm ON dp.machine_id = wm.machine_id
                                WHERE dp.production_date = @Date
                                GROUP BY wm.worker_id",
                                new { Date = summaryDate }, tran);

                            // 5. 更新 cnc_machine_daily_status
                            conn.Execute(@"DELETE FROM cnc_machine_daily_status WHERE production_date = @Date",
                                new { Date = summaryDate }, tran);

                            // 有采集记录的 → normal
                            conn.Execute(@"INSERT INTO cnc_machine_daily_status (machine_id, production_date, data_status, created_at, updated_at)
                                SELECT DISTINCT machine_id, @Date, 'normal', NOW(), NOW()
                                FROM cnc_collect_record WHERE DATE(collect_time) = @Date",
                                new { Date = summaryDate }, tran);

                            // 未开机 → offline
                            conn.Execute(@"INSERT INTO cnc_machine_daily_status (machine_id, production_date, data_status, created_at, updated_at)
                                SELECT m.id, @Date, 'offline', NOW(), NOW()
                                FROM cnc_machine m
                                WHERE m.is_enabled = 1 AND m.id NOT IN (
                                    SELECT DISTINCT machine_id FROM cnc_collect_record WHERE DATE(collect_time) = @Date
                                ) AND m.id NOT IN (
                                    SELECT machine_id FROM cnc_machine_daily_status WHERE production_date = @Date
                                )",
                                new { Date = summaryDate }, tran);

                            tran.Commit();
                        }
                        catch
                        {
                            tran.Rollback();
                            throw;
                        }
                    }
                }

                sw.Stop();
                _log.Info($"========== 日终汇总完成（日期={summaryDate:yyyy-MM-dd}, 耗时={sw.ElapsedMilliseconds}ms） ==========");
                return true;
            }
            catch (Exception ex)
            {
                _log.Error($"日终汇总失败（日期={summaryDate:yyyy-MM-dd}）", ex);
                // 写入告警：日终汇总失败意味着产量统计缺失
                try
                {
                    using (var conn2 = new MySqlConnection(_businessConnStr))
                    {
                        conn2.Execute(@"INSERT INTO cnc_alert (alert_type, title, detail, is_resolved, created_at)
                            VALUES (@Type, @Title, @Detail, 0, NOW())",
                            new { Type = "summary_error", Title = $"日终汇总失败({summaryDate:yyyy-MM-dd})",
                                Detail = ex.Message });
                    }
                }
                catch { /* 告警写入失败不影响主流程 */ }
                return false;
            }
        }
    }
}
