using Dapper;
using Dapper.Contrib.Extensions;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MySql.Data.MySqlClient;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace Performance.Services
{
    public class LogManageService : IAutoInjection
    {
        private readonly ILogger<LogManageService> logger;
        private readonly IHubContext<AllotLogHub> hubContext;
        private readonly IOptions<AppConnection> _options;
        private readonly WebapiUrl url;

        public LogManageService(
            ILogger<LogManageService> logger,
            IHubContext<AllotLogHub> hubContext,
            IOptions<WebapiUrl> url,
            IOptions<AppConnection> options)
        {
            this.logger = logger;
            this.hubContext = hubContext;
            _options = options;
            this.url = url.Value;
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="tag">标签</param>
        /// <param name="message">内容</param>
        /// <param name="level">等级1、信息（info）2、警告（warn）3、错误（error）4、异常（exception）5、成功（success）</param>
        /// <param name="allotId">绩效Id</param>
        /// <param name="method">方法名称</param>
        public void WriteMsg(string tag, string message, int level, int allotId, string method, bool isDebug = false)
        {
            logger.LogInformation($"method:{method};tag:{tag}; message:{message}; level:{level}");
            hubContext.Clients.Group(allotId.ToString()).SendAsync(method, tag, message, level);
            if (isDebug)
            {
                Insert(allotId, tag, message, level, 1);
            }
        }

        private void Insert(int allotId, string tag, string message, int level, int type)
        {
            using (IDbConnection connection = new MySqlConnection(_options.Value.PerformanceConnectionString))
            {
                connection.Insert<log_dbug>(new log_dbug { AllotID = allotId, CreateTime = DateTime.Now, Title = tag, Message = message, Level = level, Type = type });
            }
        }

        /// <summary>
        /// 抽取进度
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="ratio"></param>
        /// <param name="level">等级1、信息（info）2、警告（warn）3、错误（error）4、异常（exception）5、成功（success）</param>
        /// <param name="success"></param>
        public void Schedule(string groupName, decimal ratio, int level)
        {
            hubContext.Clients.Group(groupName).SendAsync("Schedule", ratio, level);
        }

        /// <summary>
        /// 抽取日志
        /// </summary>
        /// <param name="groupName"></param>
        /// <param name="tag"></param>
        /// <param name="message"></param>
        /// <param name="level">等级1、信息（info）2、警告（warn）3、错误（error）4、异常（exception）5、成功（success）</param>
        public void ExtractLog(string groupName, string tag, string message, int level)
        {
            hubContext.Clients.Group(groupName).SendAsync("ExtractLog", tag, message, level);
        }

        /// <summary>
        ///
        /// </summary>
        /// <param name="allotId"></param>
        /// <param name="groupName"></param>
        /// <param name="type">1、绩效生成日志 2、绩效提取日志 3、绩效提取进度</param>
        /// <param name="tag"></param>
        /// <param name="message"></param>
        /// <param name="level">1、信息（info）2、警告（warn）3、错误（error）4、异常（exception）5、成功（success）</param>
        /// <param name="isSingle"></param>
        public void ReturnTheLog(int allotId, string groupName, int type, string tag, object message, int level = 1, bool isSingle = false)
        {
            try
            {
                string content = ""; decimal ratio = 0;
                if (type == 2)
                {
                    content = message.ToString();
                    logger.LogInformation(content);
                    if (isSingle) hubContext.Clients.Group(groupName).SendAsync("ExtractLog", tag, content, level);
                }
                else if (type == 3)
                {
                    ratio = Math.Round(Convert.ToDecimal(message), 2, MidpointRounding.AwayFromZero);
                    if (level != 5 && ratio > 100) ratio = 99;
                    if (level == 5 && ratio != 100) ratio = 100;
                    content = ratio.ToString();
                    if (isSingle) hubContext.Clients.Group(groupName).SendAsync("Schedule", ratio, level);
                }

                Insert(allotId, tag, content, level, type);
                if (!isSingle)
                {
                    var http = new RestSharpHelper();
                    var importUrl = http.SetUrl(url.ImportFile, "template/returnlog");
                    var info = new SignalrLogRequest()
                    {
                        Type = type,
                        Tag = tag,
                        Message = content,
                        Level = level,
                        GroupName = groupName
                    };
                    string json = JsonHelper.Serialize(info);
                    var request = http.CreatePostRequest(json);

                    Task.Run(() => http.GetResponse(importUrl, request));
                }
            }
            catch (Exception ex)
            {
                logger.LogInformation("发送日志失败：" + ex.ToString());
            }
        }

        public int ClearExtractLog(int allotId)
        {
            using (IDbConnection connection = new MySqlConnection(_options.Value.PerformanceConnectionString))
            {
                return connection.Execute("delete from log_dbug where AllotID = @allotId and Type in @type", new { allotId, type = new int[] { 2, 3 } });
            }
        }

        //todo:log信息展示
        public List<log_dbug> GetLogDbug(int allotId)
        {
            using (IDbConnection connection = new MySqlConnection(_options.Value.PerformanceConnectionString))
            {
                var logs = connection.Query<log_dbug>("select * from log_dbug where AllotID = @allotId and Type = @type", new { allotId, type = 2 });
                return logs == null || logs.Count() == 0 ? new List<log_dbug>() : logs.ToList();
            }
        }
    }
}
