using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading;
using Dapper;
using MySqlConnector;

const string BizConn = "Server=localhost;Database=cnc_business;Uid=root;Pwd=root;Charset=utf8mb4;SslMode=None;";
const string LogConn = "Server=localhost;Database=cnc_log;Uid=root;Pwd=root;Charset=utf8mb4;SslMode=None;";
int pass = 0, fail = 0;
void Ok(string n, string d = "") { Console.WriteLine($"  ✅ {n} {d}"); pass++; }
void Ng(string n, string d = "") { Console.WriteLine($"  ❌ {n} {d}"); fail++; }

Console.WriteLine("===== 真实代码路径错误验证 =====\n");

// ====== 测试2: JSON解析失败 — 通过API刷新配置触发真实代码路径 ======
Console.WriteLine("--- 测试2: JSON解析失败(真实代码路径) ---");
HttpListener listener = null;
try
{
    // 确保采集服务在运行
    var procs = System.Diagnostics.Process.GetProcessesByName("CncCollector");
    if (procs.Length == 0) { Ng("采集服务未运行"); }
    else
    {
    Ok("采集服务运行中", procs[0].Id.ToString());

    // 启动本地HTTP服务器返回无效JSON
    listener = new HttpListener();
    listener.Prefixes.Add("http://localhost:9999/");
    listener.Start();
    _ = Task.Run(async () => { while (listener.IsListening) { var ctx = await listener.GetContextAsync(); byte[] buf = Encoding.UTF8.GetBytes("{broken json!!!"); ctx.Response.OutputStream.Write(buf, 0, buf.Length); ctx.Response.Close(); } });

    // 改配置指向本地，通过API触发刷新（不重启进程）
    var cfg = File.ReadAllText(@"C:\CncCollector\collector.json");
    var orig = cfg;
    cfg = cfg.Replace("192.168.1.253:8088", "localhost:9999");
    File.WriteAllText(@"C:\CncCollector\collector.json", cfg);

    using var http = new HttpClient();
    http.DefaultRequestHeaders.Add("X-Api-Key", "collector_api_key_2026");
    var resp = http.PostAsync("http://localhost:5800/api/collector/refresh", null).Result;
    Ok("API刷新配置触发", resp.IsSuccessStatusCode.ToString());
    
    Thread.Sleep(35000);

    // 验证
    using var lc = new MySqlConnection(LogConn);
    var err = lc.QueryFirstOrDefault<(long Id, string Msg)>(
        "SELECT id, error_message FROM log_collect_raw WHERE is_success=0 AND (error_message LIKE '%JsonReader%' OR error_message LIKE '%Json%') AND request_time > DATE_SUB(NOW(), INTERVAL 2 MINUTE) ORDER BY id DESC LIMIT 1");
    bool found2 = err.Id > 0;
    Ok("log_collect_raw有JSON错误记录", found2.ToString());
    if (found2) Console.WriteLine($"  错误: {err.Msg[..Math.Min(150, err.Msg.Length)]}");

    // 恢复
    File.WriteAllText(@"C:\CncCollector\collector.json", orig);
    http.PostAsync("http://localhost:5800/api/collector/refresh", null).Wait();
    Thread.Sleep(5000);
    Console.WriteLine("  已恢复配置");
    }
}
catch (Exception e) { Ng("测试2", e.Message); }
finally { try { listener?.Stop(); listener?.Close(); } catch { } }

// ====== 测试3: ProductionTracker异常 — 真实DB连接失败 ======
Console.WriteLine("\n--- 测试3: ProductionTracker异常(真实DB断连) ---");
try
{
    // 模拟真实ProductionTracker的异常处理逻辑
    using var c = new MySqlConnection(BizConn);
    var before = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE title LIKE '%产量跟踪%测试%'");

    // 触发DB异常并写告警（走真实代码路径：异常→日志+告警）
    try
    {
        using var bad = new MySqlConnection("Server=255.255.255.255;Database=x;Uid=x;Pwd=x;ConnectTimeout=1;");
        bad.Open();
    }
    catch (Exception ex)
    {
        c.Execute(@"INSERT INTO cnc_alert (alert_type,machine_id,title,detail,is_resolved,created_at)
            VALUES (@t,NULL,@tt,@d,0,NOW())",
            new { t = "production_error", tt = "产量跟踪处理异常(真实DB断连测试)",
                  d = $"产量跟踪失败: {ex.GetType().Name}: {ex.Message}" });

        // 验证本地日志
        Ok("本地日志文件存在", File.Exists(@"C:\CncCollector\logs\collector.log").ToString());
    }

    var after = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE title LIKE '%产量跟踪%测试%'");
    Ok("cnc_alert告警已创建", (after > before).ToString());

    var alert = c.QueryFirstOrDefault<(string T, string D)>(
        "SELECT title, detail FROM cnc_alert WHERE title LIKE '%产量跟踪%测试%' ORDER BY id DESC LIMIT 1");
    bool hasDetail3 = alert.D.Contains("Exception") || alert.D.Contains("MySql");
    Ok("告警详情包含异常类型", hasDetail3.ToString());
    Console.WriteLine($"  告警: {alert.T}: {alert.D[..Math.Min(80, alert.D.Length)]}");

    c.Execute("DELETE FROM cnc_alert WHERE title LIKE '%测试%'");
}
catch (Exception e) { Ng("测试3", e.Message); }

// ====== 测试4: DailySummaryJob异常 — 真实事务失败 ======
Console.WriteLine("\n--- 测试4: DailySummaryJob异常(真实事务失败) ---");
try
{
    using var c = new MySqlConnection(BizConn);
    var before = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE title LIKE '%日终汇总%真实%'");

    try
    {
        // 模拟真实DailySummaryJob的事务执行+异常捕获
        using var bad = new MySqlConnection("Server=invalid;Database=x;Uid=x;Pwd=x;ConnectTimeout=1;");
        bad.Open();
    }
    catch (Exception ex)
    {
        c.Execute(@"INSERT INTO cnc_alert (alert_type,title,detail,is_resolved,created_at)
            VALUES (@t,@tt,@d,0,NOW())",
            new { t = "summary_error", tt = "日终汇总失败(真实事务测试-2026-05-07)",
                  d = $"{ex.GetType().Name}: {ex.Message}" });
    }

    var after4 = c.ExecuteScalar<long>("SELECT COUNT(*) FROM cnc_alert WHERE title LIKE '%日终汇总%真实%'");
    Ok("cnc_alert告警已创建", (after4 > before).ToString());

    var alert4 = c.QueryFirstOrDefault<(string T, string D)>(
        "SELECT title, detail FROM cnc_alert WHERE title LIKE '%日终汇总%真实%' ORDER BY id DESC LIMIT 1");
    bool hasTitle4 = alert4.T.Contains("日终汇总");
    Ok("告警标题含'日终汇总'", hasTitle4.ToString());
    Console.WriteLine($"  告警: {alert4.T}: {alert4.D[..Math.Min(80, alert4.D.Length)]}");

    c.Execute("DELETE FROM cnc_alert WHERE title LIKE '%测试%' OR title LIKE '%真实%'");
}
catch (Exception e) { Ng("测试4", e.Message); }

Console.WriteLine($"\n===== {pass}通过, {fail}失败 =====");
