using AutoNotificatPhone.Controllers;
using Common;
using System.Threading;
using NLog;
using System.Diagnostics;
using Npgsql;
using Microsoft.Extensions.Configuration;

namespace AutoNotificatPhone.Models
{
    public class TimerClass : BackgroundService
    {
        // 日志记录器
        public static Logger logger = LogManager.GetCurrentClassLogger();
        // 通知接收手机号码
        private static readonly string Mobile1 = "13509214696";
        private static readonly string Mobile2 = "16620970520";
        // 记录已执行任务的时间点
        private Dictionary<DateTime, bool> _executedTasks = [];
        // 消息控制器实例
        private readonly CallAndMsgController _callAndMsgController = new();
        private readonly IConfiguration _configuration;

        public TimerClass(IConfiguration configuration)
        {
            _configuration = configuration;
        }

        /// <summary>
        /// 后台服务主执行方法
        /// </summary>
        protected override async Task ExecuteAsync(CancellationToken cancellationToken)
        {
            await Task.Factory.StartNew(async () =>
            {
                while (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        // 计算下次执行时间（每分钟的30秒）
                        var now = DateTime.UtcNow;
                        var nextRunTime = CalculateNextRunTime(now);
                        var delayTime = nextRunTime - now;

                        // 等待到下一个执行点
                        await Task.Delay(delayTime, cancellationToken);

                        // 检查电话机状态并记录日志
                        LogPhoneStatus(CheckPhoneIsOnline());

                        // 执行定时任务
                        await RegularlySendActiverecords();

                        // 执行系统检查任务
                        await CheckCpuThresholdAsync();
                        await CheckRcuOnlineAsync();
                        await CheckTotalSendPackageAsync();
                        await CheckTotalRecvPackageAsync();
                        await CheckKafkaHeartbeatAsync();
                    }
                    catch (TaskCanceledException)
                    {
                        // 任务被取消时的处理
                        logger.Error("任务被取消");
                        break;
                    }
                    catch (Exception ex)
                    {
                        // 异常处理
                        logger.Error($"主循环发生错误: {ex.Message}");
                        await Task.Delay(TimeSpan.FromSeconds(10), cancellationToken);
                    }
                }
            }, TaskCreationOptions.LongRunning);
        }

        /// <summary>
        /// 计算下次执行时间（每分钟的30秒）
        /// </summary>
        private DateTime CalculateNextRunTime(DateTime now)
        {
            var nextRunTime = new DateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, 30);
            return now.Second >= 30 ? nextRunTime.AddMinutes(1) : nextRunTime;
        }

        /// <summary>
        /// 记录电话机状态日志
        /// </summary>
        private void LogPhoneStatus(bool isOnline)
        {
            logger.Error(isOnline ? "电话机在线，开始判断！+++++str+++++" : "电话机不在线，下面内容可能不会执行！+++++err+++++");
        }

        /// <summary>
        /// 检查电话机进程是否在线
        /// </summary>
        private bool CheckPhoneIsOnline()
        {
            try
            {
                // 通过进程名检查电话机是否运行
                return Process.GetProcessesByName("Telephone").Length > 0;
            }
            catch (Exception ex)
            {
                logger.Error($"电话机进程检查失败: {ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 定时发送活动记录（整点任务）
        /// </summary>
        private async Task RegularlySendActiverecords()
        {
            // 转换为北京时间
            var beijingTime = DateTime.UtcNow.AddHours(8);
            //logger.Error($"每日任务检查 - 当前北京时间: {beijingTime:yyyy-MM-dd HH:mm:ss}");

            // 检查是否整点
            if (beijingTime.Minute != 0)
            {
                //logger.Error($"不满足整点任务触发条件 - 当前时间: {beijingTime:HH:mm}");
                return;
            }

            // 创建整点时间键
            var hourlyKey = new DateTime(beijingTime.Year, beijingTime.Month, beijingTime.Day, beijingTime.Hour, 0, 0);

            // 检查任务是否已执行
            if (_executedTasks.ContainsKey(hourlyKey))
            {
                //logger.Error($"跳过已执行的整点任务 - 时间点: {hourlyKey:yyyy-MM-dd HH:mm}");
                return;
            }

            logger.Error($"准备执行整点短信任务 - 时间点: {hourlyKey:yyyy-MM-dd HH:mm}");

            // 判断执行每日任务还是整点短信
            if (beijingTime.Hour is 10 or 15 or 22)
            {
                await ExecuteDailyTask(beijingTime);
            }
            else
            {
                await SendHourlySms(beijingTime);
            }

            // 标记任务已执行
            _executedTasks[hourlyKey] = true;

            // 清理过期任务记录
            CleanupOldTasks(beijingTime);

            //logger.Error($"整点任务执行完成 - 时间点: {hourlyKey:yyyy-MM-dd HH:mm}");
        }

        /// <summary>
        /// 清理过期任务记录
        /// </summary>
        private void CleanupOldTasks(DateTime currentTime)
        {
            // 找出所有过期的任务键
            var keysToRemove = _executedTasks.Keys.Where(k => k.Date < currentTime.Date).ToList();
            foreach (var key in keysToRemove)
            {
                _executedTasks.Remove(key);
                //logger.Error($"清理过期任务记录: {key:yyyy-MM-dd HH:mm}");
            }
        }

        /// <summary>
        /// 发送整点短信
        /// </summary>
        private async Task SendHourlySms(DateTime beijingTime)
        {
            try
            {
                // 准备短信内容
                long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                string dateTimeStr = $"{beijingTime.Month}月{beijingTime.Day}日{beijingTime.Hour}点";
                string smsContent = $"[BLV运维提示] 整点系统状态报告。当前时间：{dateTimeStr}";

                // 创建短信请求
                var request = CreateSmsRequest(
                    type: "2",
                    deadline: currentTimestamp + 1800,
                    phone: Mobile1,
                    caller: "整点报告",
                    content: smsContent
                );

                // 发送短信并记录结果
                var result = _callAndMsgController.SendToPhone(request);
                /*logger.Error(result.isok
                    ? $"整点短信已发送：{dateTimeStr}"
                    : $"发送整点短信失败：{result.message}");*/
            }
            catch (Exception ex)
            {
                logger.Error($"发送整点短信时出错：{ex.Message}");
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 执行每日定时任务（10点、15点、22点）
        /// </summary>
        private async Task ExecuteDailyTask(DateTime beijingTime)
        {
            try
            {
                // 准备消息内容
                long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
                string dateTimeStr = $"{beijingTime.Month}月{beijingTime.Day}日{beijingTime.Hour}点";
                string smsContent = $"[BLV运维提示] 每日定时通知。当前时间为：{dateTimeStr}";
                string callContent = $"BLV运维提示 每日定时通知 当前时间为 {dateTimeStr}";

                // 创建短信和电话请求
                var smsRequest1 = CreateSmsRequest("2", currentTimestamp + 1800, Mobile1, "每日定时通知", smsContent);
                var smsRequest2 = CreateSmsRequest("2", currentTimestamp + 1800, Mobile2, "每日定时通知", smsContent);
                var callRequest = CreateSmsRequest("1", currentTimestamp + 900, Mobile1, "每日定时通知", callContent);

                // 发送通知
                var smsResult1 = _callAndMsgController.SendToPhone(smsRequest1);
                var smsResult2 = _callAndMsgController.SendToPhone(smsRequest2);
                var callResult = _callAndMsgController.SendToPhone(callRequest);

                // 记录发送结果
                if (smsResult1.isok && smsResult2.isok && callResult.isok)
                {
                    //logger.Error($"每日定时通知已发送：{dateTimeStr}");
                }
                else
                {
                    logger.Error($"发送每日定时通知失败：短信1={smsResult1.message} 短信2={smsResult2.message} 电话={callResult.message}");
                }
            }
            catch (Exception ex)
            {
                logger.Error($"执行每日任务时出错：{ex.Message}");
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 检查CPU使用率阈值
        /// </summary>
        private async Task CheckCpuThresholdAsync()
        {
            try
            {
                // 检查监控程序是否在线
                string detectTimeString = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_DetectTime");
                if (!string.IsNullOrEmpty(detectTimeString) &&
                    DateTime.TryParse(detectTimeString, out DateTime detectTime) &&
                    (DateTime.UtcNow - detectTime).TotalMinutes > 10)
                {
                    // 监控程序无法访问警报
                    ExecuteMonitorUnavailableAlert(detectTime);
                    return;
                }

                // 获取CPU使用率数据
                string cpuMax = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_CPUMax");
                string cpuAvg = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_CPUAvg");
                List<int> cpuMaxValues = ParseCpuValues(cpuMax);
                List<int> cpuAvgValues = ParseCpuValues(cpuAvg);

                // 记录CPU使用率
                //logger.Error($"RCU服务器的CPU使用率-AVG:{cpuAvg},MAX:{cpuMax}");

                // 检查是否超过阈值
                if (CheckThreshold(cpuAvgValues, 80, 6))//(CheckThreshold(cpuMaxValues, 90, 6) || CheckThreshold(cpuAvgValues, 85, 6))
                {
                    // 触发CPU警报
                    ExecuteCpuAlert(cpuMaxValues, ParseCpuValues(CSRedisCacheHelper.redis1.Get<string>("UDPPackage_CPUMin")), cpuAvgValues);
                }
            }
            catch (Exception ex)
            {
                logger.Error($"CPU阈值检查错误: {ex.Message}");
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 检查RCU在线数量
        /// </summary>
        private async Task CheckRcuOnlineAsync()
        {
            await CheckRedisValueAsync("RCUOnLine", 8, 0.8, ExecuteRcuOnlineAlert, "RCU主机的在线数量");
        }

        /// <summary>
        /// 检查总发送包数量
        /// </summary>
        private async Task CheckTotalSendPackageAsync()
        {
            await CheckRedisValueAsync("UDPPackage_TotalSendPackage", 8, 0.6, ExecuteTotalSendPackageAlert, "RCU主机的通讯数量");
        }
        /// <summary>
        /// 检查总接收包数量
        /// </summary>
        private async Task CheckTotalRecvPackageAsync()
        {
            try
            {
                // 从Redis获取值
                string valueString = CSRedisCacheHelper.redis1.Get<string>("UDPPackage_TotalRecvPackage");
                if (string.IsNullOrEmpty(valueString)) return;

                // 解析值
                List<int> values = ParseCpuValues(valueString);
                if (values == null || values.Count < 10) return;

                // 检查最后3个值是否都小于70000
                if (values.Count >= 3 && values[^3] < 70000 && values[^2] < 70000 && values[^1] < 70000)
                {
                    // 触发警报
                    ExecuteTotalRecvPackageAlert([values[^3], values[^2], values[^1]]);
                }
                else
                {
                    // 原有的阈值检查逻辑
                    await CheckRedisValueAsync("UDPPackage_TotalRecvPackage", 8, 0.75, ExecuteTotalRecvPackageAlert, "RCU主机的通讯数量");
                }
            }
            catch (Exception ex)
            {
                logger.Error($"总接收包数量检查错误: {ex.Message}");
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 通用Redis值检查方法
        /// </summary>
        private async Task CheckRedisValueAsync(string redisKey, int baselineCount, double thresholdRatio, Action<List<int>> alertAction, string logPrefix)
        {
            try
            {
                // 从Redis获取值
                string valueString = CSRedisCacheHelper.redis1.Get<string>(redisKey);
                if (string.IsNullOrEmpty(valueString)) return;

                // 解析值
                List<int> values = ParseCpuValues(valueString);
                if (values == null || values.Count < 10) return;

                // 计算平均值和阈值
                double average = values.Take(baselineCount).Average();
                double threshold = average * thresholdRatio;
                //logger.Error($"{logPrefix}-AVG:{average},ALL:{valueString}");

                // 检查最后两个值是否低于阈值
                if (values[baselineCount] < threshold && values[baselineCount + 1] < threshold)
                {
                    // 触发警报
                    alertAction(values);
                }
            }
            catch (Exception ex)
            {
                logger.Error($"{logPrefix}检查错误: {ex.Message}");
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 执行RCU在线数量警报
        /// </summary>
        private void ExecuteRcuOnlineAlert(List<int> values)
        {
            SendAlert(
                smsContent: $"[BLV运维提示] RCU主机在线数量低于正常值，请立即检查。数据：{string.Join(",", values)}",
                callContent: "BLV运维提示 RCU主机在线数量低于正常值 请立即检查",
                alertType: "RCU-在线数量警报"
            );
        }

        /// <summary>
        /// 执行总发送包数量警报
        /// </summary>
        private void ExecuteTotalSendPackageAlert(List<int> values)
        {
            SendAlert(
                smsContent: $"[BLV运维提示] RCU发送数量低于预期值，请立即检查。数据：{string.Join(",", values)}",
                callContent: "BLV运维提示 RCU发送数量低于预期值 请立即检查",
                alertType: "RCU-通讯数量警报"
            );
        }
        /// <summary>
        /// 执行总接收包数量警报
        /// </summary>
        private void ExecuteTotalRecvPackageAlert(List<int> values)
        {
            SendAlert(
                smsContent: $"[BLV运维提示] RCU接收数量低于预期值，请立即检查。数据：{string.Join(",", values)}",
                callContent: "BLV运维提示 RCU接收数量低于预期值 请立即检查",
                alertType: "RCU-通讯数量警报"
            );
        }

        /// <summary>
        /// 执行CPU使用率警报
        /// </summary>
        private void ExecuteCpuAlert(List<int> cpuMax, List<int> cpuMin, List<int> cpuAvg)
        {
            string dataString = $"AVG:{string.Join(",", cpuAvg)},MAX:{string.Join(",", cpuMax)},MIN:{string.Join(",", cpuMin)}";
            SendAlert(
                smsContent: $"[BLV运维提示] RCU服务器的CPU使用率告警。{dataString}",
                callContent: "BLV运维提示 RCU服务器的CPU使用率告警 请立即检查",
                alertType: "RCU-CPU警报"
            );
        }

        /// <summary>
        /// 执行监控程序无法访问警报
        /// </summary>
        private void ExecuteMonitorUnavailableAlert(DateTime detectTime)
        {
            SendAlert(
                smsContent: "[BLV运维提示] RCU服务器的监控程序无法访问，请立即检查。",
                callContent: "BLV运维提示 RCU服务器的监控程序无法访问 请立即检查",
                alertType: "RCU-监控程序警报",
                extendedDeadline: true
            );
        }

        /// <summary>
        /// 检查Kafka入库心跳（PostgreSQL）
        /// </summary>
        private async Task CheckKafkaHeartbeatAsync()
        {
            try
            {
                string? connectionString = BuildPostgresConnectionString();
                if (string.IsNullOrWhiteSpace(connectionString))
                {
                    logger.Error("Postgres配置缺失，无法检查Kafka入库心跳");
                    ExecuteKafkaDbConnectionAlert();
                    return;
                }

                await using var connection = new NpgsqlConnection(connectionString);
                await connection.OpenAsync();

                const string sql = "select ts_ms from heartbeat.heartbeat_events order by ts_ms desc limit 1";
                await using var command = new NpgsqlCommand(sql, connection);
                object? result = await command.ExecuteScalarAsync();

                if (result == null || result == DBNull.Value)
                {
                    ExecuteKafkaDbConnectionAlert();
                    return;
                }

                if (!long.TryParse(result.ToString(), out long lastTsMs))
                {
                    logger.Error("Kafka入库心跳ts_ms解析失败");
                    ExecuteKafkaDbConnectionAlert();
                    return;
                }

                long nowMs = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
                if (nowMs - lastTsMs > TimeSpan.FromMinutes(2).TotalMilliseconds)
                {
                    ExecuteKafkaInactiveAlert();
                }
            }
            catch (Exception ex)
            {
                logger.Error($"Kafka入库心跳检查错误: {ex.Message}");
                ExecuteKafkaDbConnectionAlert();
            }
            await Task.CompletedTask;
        }

        /// <summary>
        /// 生成PostgreSQL连接字符串
        /// </summary>
        private string? BuildPostgresConnectionString()
        {
            IConfigurationSection section = _configuration.GetSection("Postgres");
            string? host = section["Host"];
            string? portString = section["Port"];
            string? database = section["Database"];
            string? username = section["User"];
            string? password = section["Password"];
            string? maxConnectionsString = section["MaxConnections"];
            string? idleTimeoutMsString = section["IdleTimeoutMs"];

            if (string.IsNullOrWhiteSpace(host) ||
                string.IsNullOrWhiteSpace(portString) ||
                string.IsNullOrWhiteSpace(database) ||
                string.IsNullOrWhiteSpace(username) ||
                string.IsNullOrWhiteSpace(password))
            {
                return null;
            }

            if (!int.TryParse(portString, out int port))
            {
                return null;
            }

            var builder = new NpgsqlConnectionStringBuilder
            {
                Host = host,
                Port = port,
                Database = database,
                Username = username,
                Password = password
            };

            if (int.TryParse(maxConnectionsString, out int maxConnections) && maxConnections > 0)
            {
                builder.MaxPoolSize = maxConnections;
            }

            if (int.TryParse(idleTimeoutMsString, out int idleTimeoutMs) && idleTimeoutMs > 0)
            {
                builder.ConnectionIdleLifetime = Math.Max(1, idleTimeoutMs / 1000);
            }

            return builder.ConnectionString;
        }

        /// <summary>
        /// 执行Kafka入库失活警报
        /// </summary>
        private void ExecuteKafkaInactiveAlert()
        {
            SendAlert(
                smsContent: "[BLV运维提示] BLS数据库1分钟内入库数据为0。",
                callContent: "BLV运维提示 BLS数据库1分钟内入库数据为0",
                alertType: "BLS-数据库入库警报",
                extendedDeadline: true
            );
        }

        /// <summary>
        /// 执行Kafka入库数据库连接失败警报
        /// </summary>
        private void ExecuteKafkaDbConnectionAlert()
        {
            SendAlert(
                smsContent: "[BLV运维提示] 数据库连接失败！",
                callContent: "[BLV运维提示] 数据库连接失败",
                alertType: "BLS-数据库连接警报",
                extendedDeadline: true
            );
        }

        /// <summary>
        /// 解析CPU值字符串为整数列表
        /// </summary>
        private List<int> ParseCpuValues(string valueString)
        {
            return string.IsNullOrEmpty(valueString)
                ? new List<int>()
                : valueString.Split(',').Select(v => int.TryParse(v, out int result) ? result : 0).ToList();
        }

        /// <summary>
        /// 检查值列表是否超过阈值
        /// </summary>
        private bool CheckThreshold(List<int> values, int threshold, int requiredCount)
        {
            return values != null &&
                   values.Count >= requiredCount &&
                   values.Count(v => v >= threshold) >= requiredCount;
        }


        /// <summary>
        /// 通用警报发送方法
        /// </summary>
        private void SendAlert(string smsContent, string callContent, string alertType, bool extendedDeadline = false)
        {
            // 设置过期时间
            long currentTimestamp = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
            long smsDeadline = extendedDeadline ? currentTimestamp + 3600 : currentTimestamp + 1800;
            long callDeadline = extendedDeadline ? currentTimestamp + 1800 : currentTimestamp + 900;

            // 创建请求
            var smsRequest = CreateSmsRequest("2", smsDeadline, Mobile1, alertType, smsContent);
            var smsRequest2 = CreateSmsRequest("2", smsDeadline, Mobile2, alertType, smsContent);
            var callRequest = CreateSmsRequest("1", callDeadline, Mobile1, alertType, callContent);

            // 发送警报
            var smsResult = _callAndMsgController.SendToPhone(smsRequest);
            var smsResult2 = _callAndMsgController.SendToPhone(smsRequest2);
            var callResult = _callAndMsgController.SendToPhone(callRequest);

            // 记录结果
            if (smsResult.isok && callResult.isok)
            {
                //logger.Error($"{alertType}警告已发送");
            }
            else
            {
                logger.Error($"发送{alertType}通知失败: 短信={smsResult.message} 电话={callResult.message}");
            }
        }

        /// <summary>
        /// 创建短信/电话请求对象
        /// </summary>
        private SmsRequest CreateSmsRequest(string type, long deadline, string phone, string caller, string content)
        {
            return new SmsRequest
            {
                Type = type,
                DeadLine = deadline,
                StartingPoint = DateTimeOffset.UtcNow.ToUnixTimeSeconds(),
                PhoneNumber = phone,
                CallerName = caller,
                Content = content
            };
        }

    }
}