using DotNetCore.CAP;
using Furion;
using Furion.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Serilog;
using Serilog.Events;
using SuperSocket;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Furion.DataEncryption.Extensions;

namespace Waste.SocketService
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .UseWindowsService()
            .Inject()
             //日志注入,将serilog设置为日志记录提供程序
             .UseSerilogDefault(config =>
             {
                 var filepath = App.Configuration["logfile"];
                 string date = DateTime.Now.ToString("yyyy-MM-dd");//按时间创建文件夹
                 string outputTemplate = "{NewLine}【{Level:u3}】{Timestamp:yyyy-MM-dd HH:mm:ss.fff}" +
                  "{NewLine}#Msg#{Message:lj}" +
                  "{NewLine}#Pro #{Properties:j}" +
                  "{NewLine}#Exc#{Exception}" +
                  new string('-', 50);//输出模板
                                      //1.输出所有restrictedToMinimumLevel：LogEventLevel类型
                 config
                     .Enrich.WithProperty("Application", typeof(Program).Assembly.GetName().Name)
                     .Enrich.WithProcessId()
                     .Enrich.WithProcessName()
                     .WriteTo.Console()
                       .WriteTo.Seq("http://localhost:5341/")

          //2.1仅输出 LogEventLevel.Debug 类型
          .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Debug)//筛选过滤
              .WriteTo.File($"{filepath}/{date}/{LogEventLevel.Debug}.log",
                  outputTemplate: outputTemplate,
                  rollingInterval: RollingInterval.Day,//日志按日保存，这样会在文件名称后自动加上日期后缀
                  encoding: Encoding.UTF8            // 文件字符编码
               )
                      )

          //2.2仅输出 LogEventLevel.Error 类型
          .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Error)//筛选过滤
              .WriteTo.File($"{filepath}/{date}/{LogEventLevel.Error}.log",
                  outputTemplate: outputTemplate,
                  rollingInterval: RollingInterval.Day,//日志按日保存，这样会在文件名称后自动加上日期后缀
                  encoding: Encoding.UTF8            // 文件字符编码
               )
             )
          .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Information)//筛选过滤
              .WriteTo.File($"{filepath}/{date}/{LogEventLevel.Information}.log",
                  outputTemplate: outputTemplate,
                  rollingInterval: RollingInterval.Day,//日志按日保存，这样会在文件名称后自动加上日期后缀
                  encoding: Encoding.UTF8            // 文件字符编码
               )
             )
            .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Fatal)//筛选过滤
              .WriteTo.File($"{filepath}/{date}/{LogEventLevel.Fatal}.log",
                  outputTemplate: outputTemplate,
                  rollingInterval: RollingInterval.Day,//日志按日保存，这样会在文件名称后自动加上日期后缀
                  encoding: Encoding.UTF8            // 文件字符编码
               )
             )
              .WriteTo.Logger(lg => lg.Filter.ByIncludingOnly(evt => evt.Level == LogEventLevel.Warning)//筛选过滤
              .WriteTo.File($"{filepath}/{date}/{LogEventLevel.Warning}.log",
                  outputTemplate: outputTemplate,
                  rollingInterval: RollingInterval.Day,//日志按日保存，这样会在文件名称后自动加上日期后缀
                  encoding: Encoding.UTF8            // 文件字符编码
               )
             )
             ;
             })
             .ConfigureServices((hostContext, services) =>
             {
                 var configuration = hostContext.Configuration;
                 //添加CAP支持
                 services.AddCap(x =>
                  {
                      x.DefaultGroupName = "jtsky.queue.waste";
                      //配置rabbitmq支持
                      string port = configuration["RabbitmqSetting:Port"];
                      int p = Convert.ToInt32(port);
                      x.UseRabbitMQ(opt =>
                      {
                          opt.HostName = configuration["RabbitmqSetting:HostName"]; //配置ip地址
                          opt.Port = p;//配置端口
                          opt.UserName = configuration["RabbitmqSetting:UserName"];//配置用户名
                          opt.Password = configuration["RabbitmqSetting:Password"];//配置Miami
                      });
                      //配置sqlserver支持
                      x.UseSqlServer(x =>
                      {
                          x.ConnectionString = configuration["RabbitmqSetting:DBConnection"];
                          x.Schema = "cap_s";
                      });
                      x.SucceedMessageExpiredAfter = 3600;
                  });
             })
             .AsSuperSocketHostBuilder<MyPackage, WastePackageFilter>()
             .UsePackageHandler(async (session, package) =>
            {
                //向rabbitmq队列发布消息
                await Scoped.Create(async (_, scope) =>
                {
                    var services = scope.ServiceProvider;
                    var _capBus = services.GetService<ICapPublisher>();
                    var _logger = services.GetService<ILogger>();
                    if (package.IsChecked)
                    {
                        string msg = $"通过校检,Key:{package.Key}十六进制:{package.Body},字符串:{package.Str}";
                        if (package.IsHeart)
                        {
                            msg = $"{msg},心跳包数据,{(package == null ? "" : JsonConvert.SerializeObject(package))}";
                        }
                        else
                        {
                            msg = $"{msg},测量数据,{(package == null ? "" : JsonConvert.SerializeObject(package))}";
                            if (package.IsWeight)
                            {
                                if (package.Key == "A8")
                                {
                                    msg = $"{msg},uuid:{package.UUID},测量时间:{package.UploadTime},垃圾类别:{package.WasteType},小类:{package.WasteSType},重量:{package.Weight},价格:{package.Price},金额:{package.Amount},操作员:{package.OpUser}";
                                }
                                else
                                {
                                    msg = $"{msg},桶大小:{package.size},垃圾桶编号:{package.trashcode},垃圾类别:{package.WasteType},重量:{package.Weight}KG";
                                }
                            }
                            else
                            {
                                msg = $"{msg},数据:{package.size}";
                            }
                        }
                        _logger.Information(msg);
                        if (package.Key == "A8")
                        {
                            package.DataHash = $"{package.Str}".ToMD5Encrypt();
                            await _capBus.PublishAsync("result.service.inserta84g", package);
                            if (!session.Channel.IsClosed)
                            {
                                if (package.IsHeart)
                                {
                                    string returndata = $"HEART,SIGNAL,{package.GSLQ}";
                                    await session.SendAsync(Encoding.GetEncoding("GB2312").GetBytes(returndata + "\r\n"));
                                }
                                else if (package.IsWeight)
                                {
                                    string returndata = $"STATUS,OK,{package.UUID}";
                                    await session.SendAsync(Encoding.GetEncoding("GB2312").GetBytes(returndata + "\r\n"));
                                }
                            }
                        }
                        else
                        {
                            await _capBus.PublishAsync("result.service.insert4g", package);
                        }
                    }
                    else
                    {
                        _logger.Information($"未通过校检,Key:{package.Key},十六进制:{package.Body},字符串:{package.Str}");
                    }
                });
            })
             ;
    }
}
