using Furion;
using Furion.DependencyInjection;
using Furion.TaskScheduler;
using Myshipping.Core.Entity;
using Myshipping.Core.Service;
using Microsoft.Extensions.DependencyInjection;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.IO;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
using Furion.Logging;

namespace Myshipping.Core.Job;

/// <summary>
/// 日志定时任务类
/// </summary>
public class LogJobWorker : ISpareTimeWorker, IDynamicApiController, ITransient
{
    // 日志暂存器,待写入
    private readonly List<SysLogEx> _sysLogExs = new();
    private readonly List<SysLogOp> _sysLogOps = new();
    private readonly List<SysLogVis> _sysLogViss = new();

    /// <summary>
    /// 定期删除异常日志
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="count"></param>
    [SpareTime("@midnight", "LogExDeletionService", Description = "后台定期删除异常日志,配置项参数:{\"daysAgo\": 30},不填默认为30",
               DoOnce = false, StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]
    public void DoDeleteLogEx(SpareTimer timer, long count)
    {
        // 判断是否有异常
        if (timer.Exception.Any())
        {
            // todo: 增加任务运行日志
        }

        // 默认值
        var daysAgo = 30;

        var sysCache = App.GetRequiredService<ISysCacheService>();

        // 获取写数据库容量阀值,新增定时任务时会将配置项写入缓存
        if (sysCache != null)
        {
            var parameters = sysCache.Get<Dictionary<string, string>>("LogDeletionService_Parameters");

            // 如果存在相关配置项
            if (parameters != null && parameters.ContainsKey("daysAgo") &&
                !string.IsNullOrEmpty(parameters["daysAgo"]))
                daysAgo = int.Parse(parameters["daysAgo"]);
        }

        Log.Information($"准备清理天{daysAgo}之前的日志LogEx");

        // 生成查询表达式
        Expression<Func<SysLogEx, bool>> expression = ex => ex.ExceptionTime < DateTime.Now.AddDays(-daysAgo);

        // 执行删除
        DoDeleteWork(expression);
    }

    /// <summary>
    /// 定期删除操作日志
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="count"></param>
    [SpareTime("@midnight", "LogOpDeletionService", Description = "后台定期删除操作日志,配置项参数:{\"daysAgo\": 30},不填默认为30",
               DoOnce = false, StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]
    public void DoDeleteLogOp(SpareTimer timer, long count)
    {
        // 判断是否有异常
        if (timer.Exception.Any())
        {
            // todo: 增加任务运行日志
        }

        // 默认值
        var daysAgo = 30;

        var sysCache = App.GetRequiredService<ISysCacheService>();

        // 获取写数据库容量阀值,新增定时任务时会将配置项写入缓存
        if (sysCache != null)
        {
            var parameters = sysCache.Get<Dictionary<string, string>>("LogOpDeletionService_Parameters");

            // 如果存在相关配置项
            if (parameters != null && parameters.ContainsKey("daysAgo") &&
                !string.IsNullOrEmpty(parameters["daysAgo"]))
                daysAgo = int.Parse(parameters["daysAgo"]);
        }

        Log.Information($"准备清理天{daysAgo}之前的日志LogOp");

        //// 生成查询表达式
        //Expression<Func<SysLogOp, bool>> expression = ex => ex.OpTime < DateTime.Now.AddDays(-daysAgo);

        //// 执行删除
        //DoDeleteWork(expression);


        var repLogOp = App.GetService<SqlSugarRepository<SysLogOp>>();
        repLogOp.Delete(x => x.OpTime < DateTime.Today.AddDays(-daysAgo));
    }

    /// <summary>
    /// 定期删除访问日志
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="count"></param>
    [SpareTime("@midnight", "LogVisDeletionService", Description = "后台定期删除访问日志,配置项参数:{\"daysAgo\": 30},不填默认为30",
               DoOnce = false, StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]
    public void DoDeleteLogVis(SpareTimer timer, long count)
    {
        // 判断是否有异常
        if (timer.Exception.Any())
        {
            // todo: 增加任务运行日志
        }

        // 默认值
        var daysAgo = 30;

        var sysCache = App.GetRequiredService<ISysCacheService>();

        // 获取写数据库容量阀值,新增定时任务时会将配置项写入缓存
        if (sysCache != null)
        {
            var parameters = sysCache.Get<Dictionary<string, string>>("LogVisDeletionService_Parameters");

            // 如果存在相关配置项
            if (parameters != null && parameters.ContainsKey("daysAgo") &&
                !string.IsNullOrEmpty(parameters["daysAgo"]))
                daysAgo = int.Parse(parameters["daysAgo"]);
        }

        Log.Information($"准备清理天{daysAgo}之前的日志LogVis");

        // 生成查询表达式
        Expression<Func<SysLogVis, bool>> expression = ex => ex.VisTime < DateTime.Now.AddDays(-daysAgo);

        // 执行删除
        DoDeleteWork(expression);
    }

    /// <summary>
    /// 后台批量写错误日志
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="count"></param>
    [SpareTime(10000, "LogExWritingService", Description = "后台批量写错误日志,配置项参数:{\"quantity\": 2},不填默认为2",
               DoOnce = false, StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]
    public void DoLogEx(SpareTimer timer, long count)
    {
        Console.ForegroundColor = ConsoleColor.Yellow;
        Console.WriteLine($"DoLogEx: {DateTime.Now}");
        return;
        //DoWork(timer, count, "LogExWritingService_Parameters", _sysLogExs);
    }

    /// <summary>
    /// 后台批量写操作日志
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="count"></param>
    [SpareTime(5000, "LogOpWritingService", Description = "后台批量写操作日志,配置项参数:{\"quantity\": 2},不填默认为2",
               DoOnce = false, StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]
    public void DoLogOp(SpareTimer timer, long count)
    {
        Console.ForegroundColor = ConsoleColor.Green;
        Console.WriteLine($"DoLogOp: {DateTime.Now}");
        return;
        //DoWork(timer, count, "LogOpWritingService_Parameters", _sysLogOps);
    }

    /// <summary>
    /// 后台批量写访问日志
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="count"></param>
    [SpareTime(8000, "LogVisWritingService", Description = "后台批量写访问日志,配置项参数:{\"quantity\": 2},不填默认为2",
               DoOnce = false, StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]
    public void DoLogVis(SpareTimer timer, long count)
    {
        Console.ForegroundColor = ConsoleColor.Cyan;
        Console.WriteLine($"DoLogVis: {DateTime.Now}");
        return;
        //DoWork(timer, count, "LogVisWritingService_Parameters", _sysLogViss);
    }

    /// <summary>
    /// 写日志
    /// </summary>
    /// <param name="timer"></param>
    /// <param name="count"></param>
    /// <param name="cacheKey"></param>
    /// <param name="logs"></param>
    /// <typeparam name="T"></typeparam>
    private void DoWork<T>(SpareTimer timer, long count, string cacheKey, List<T> logs) where T : class, new()
    {
        // 判断是否有异常
        if (timer.Exception.Any())
        {
            // todo: 增加任务运行日志
        }

        Scoped.Create((_, scope) =>
        {
            var services = scope.ServiceProvider;
            var logRep = App.GetService<ISqlSugarClient>(services);
            var sysCache = services.GetRequiredService<ISysCacheService>();

            // 默认值
            var quantity = 2;

            // 获取写数据库容量阀值,新增定时任务时会将配置项写入缓存
            if (sysCache != null)
            {
                var parameters = sysCache.Get<Dictionary<string, string>>(cacheKey);

                // 如果存在相关配置项
                if (parameters != null && parameters.ContainsKey("quantity") &&
                    string.IsNullOrEmpty(parameters["quantity"]))
                    quantity = int.Parse(parameters["quantity"]);
            }

            // 后台队列中产生了日志,取出写入暂存器
            int queue = SimpleQueue<T>.Count();
            if (queue > 0)
            {
                for (var i = 0; i < queue; i++)
                {
                    if (SimpleQueue<T>.Try(out T obj))
                        logs.Add(obj);
                }
            }

            // 达到系统配置的容量则写入数据库
            if (logs.Count > quantity)
            {
                logRep.Insertable<T>(logs).ExecuteCommand();
                logs.Clear();
            }
        });
    }

    /// <summary>
    /// 根据条件删除日志
    /// </summary>
    /// <param name="expression"></param>
    /// <typeparam name="T"></typeparam>
    private void DoDeleteWork<T>(Expression<Func<T, bool>> expression) where T : class, new()
    {
        Scoped.Create((_, scope) =>
        {
            var services = scope.ServiceProvider;
            var logRep = App.GetService<ISqlSugarClient>(services);
            logRep.Deleteable<T>(expression).ExecuteCommand();
        });
    }

    /// <summary>
    /// 后台批量删除临时文件
    /// </summary>
    [SpareTime(120000, "TemporaryDocuments", Description = "后台批量删除临时文件,配置项参数:{\"quantity\": 2},不填默认为2",
               DoOnce = false, StartNow = true, ExecuteType = SpareTimeExecuteTypes.Serial)]
    public void TemporaryDocuments(SpareTimer timer, long count)
    {
        var opt = App.GetOptions<TempFileOptions>();
        var dirAbs = opt.Path;
        var RemainHours = Convert.ToDouble(opt.RemainHours);
        var fileFullPath = Path.Combine(App.WebHostEnvironment.WebRootPath, dirAbs);
        string[] Files = Directory.GetFiles(fileFullPath);        //当前目录下的文件:  
        foreach (string it in Files)
        {
            FileInfo fi = new FileInfo(it);
            var date = fi.CreationTime.AddHours(RemainHours);
            if (date < DateTime.Now)
            {
                File.Delete(it);
            }
        }
        string[] _Files = Directory.GetDirectories(fileFullPath);        //当前目录下的文件夹:  
        if (_Files.Length > 0)
        {
            foreach (string it in _Files)
            {
                DirectoryInfo fi = new DirectoryInfo(it);
                var date = fi.CreationTime.AddHours(RemainHours);
                if (date < DateTime.Now)
                {
                    fi.Delete(true);
                }
                else
                {
                    TemporaryDirectories(it);
                }

            }
        }
    }


    public void TemporaryDirectories(string path)
    {
        var opt = App.GetOptions<TempFileOptions>();
        var RemainHours = Convert.ToDouble(opt.RemainHours);
        string[] Files = Directory.GetFiles(path);        //当前目录下的文件:  
        foreach (string it in Files)
        {
            FileInfo fi = new FileInfo(it);
            var date = fi.CreationTime.AddHours(RemainHours);
            if (date < DateTime.Now)
            {
                File.Delete(it);
            }
        }
        string[] _Files = Directory.GetDirectories(path);        //当前目录下的文件夹:  
        if (_Files.Length > 0)
        {
            foreach (string it in _Files)
            {
                TemporaryDirectories(it);
            }
        }
        else
        {
            DirectoryInfo fi = new DirectoryInfo(path);
            fi.Delete(true);
        }
    }
}