using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;
using Admin.Core.Common;
using Admin.Core.Common.Resource;
using Admin.Core.IService.ISys;
using Admin.Core.Model;
using Admin.Core.Model.Sys;
using Admin.Core.Repository;
using Admin.Core.Tasks;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Quartz;

namespace Admin.Core.Api
{
    /// <summary>
    /// 任务调度
    /// </summary>
    [Route("api/[controller]/[action]")]
    [ApiController]
    [Authorize(Permissions.Name)]
    public class SysTasksQzController : BaseApiUserController
    {
        private readonly ISysTasksQzService _tasksQzService;
        private readonly ISchedulerCenter _schedulerCenter;
        private readonly IUnitOfWork _unitOfWork;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="tasksQzService"></param>
        /// <param name="schedulerCenter"></param>
        /// <param name="unitOfWork"></param>
        /// <param name="sysUserService"></param>
        public SysTasksQzController(ISysTasksQzService tasksQzService, ISchedulerCenter schedulerCenter, IUnitOfWork unitOfWork,
            ISysUserService sysUserService) : base(sysUserService)
        {
            _sysUserService = sysUserService;
            _unitOfWork = unitOfWork;
            _tasksQzService = tasksQzService;
            _schedulerCenter = schedulerCenter;
        }

        /// <summary>
        /// 分页查询
        /// </summary>
        /// <param name="pageQuery"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<PageModel<SysTasksQz>>> GetByPage([FromBody] PageQuery<SysTasksQz> pageQuery)
        {
            Expression<Func<SysTasksQz, bool>> whereExpression = x => x.DelFlag == false;
            if (pageQuery.Query.Name.IsNotEmptyOrNull())
            {
                whereExpression = whereExpression.And(x => x.Name.Contains(pageQuery.Query.Name));
            }
            if (pageQuery.Query.JobGroup.IsNotEmptyOrNull())
            {
                whereExpression = whereExpression.And(x => x.JobGroup == pageQuery.Query.JobGroup);
            }
            if (pageQuery.Query.IsStart.IsNotEmptyOrNull())
            {
                whereExpression = whereExpression.And(x => x.IsStart == pageQuery.Query.IsStart);
            }
            if (pageQuery.DateRange.IsNotEmptyOrNull() && pageQuery.DateRange.Count > 0)
            {
                if (pageQuery.DateRange[0].IsNotEmptyOrNull())
                {
                    whereExpression = whereExpression.And(x => x.BeginTime >= pageQuery.DateRange[0]);
                }
                if (pageQuery.DateRange.Count > 1 && pageQuery.DateRange[1].IsNotEmptyOrNull())
                {
                    whereExpression = whereExpression.And(x => x.EndTime <= pageQuery.DateRange[1]);
                }
            }

            var orderBy = (pageQuery.OrderBy ?? "UpdateTime") + " " + (pageQuery.IsAsc ? "asc" : "desc");
            var data = await _tasksQzService.QueryPageAsync(whereExpression, pageQuery.Page, pageQuery.PageSize, orderBy);

            if (data.dataCount > 0)
            {
                foreach (var item in data.data)
                {
                    item.Triggers = await _schedulerCenter.GetTaskStaus(item);
                }
            }

            return Success(data);
        }

        /// <summary>
        /// 根据ID查询
        /// </summary>
        /// <param name="id">主键</param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<SysTasksQz>> GetByID(int id)
        {
            var data = await _tasksQzService.QueryByIdAsync(id);
            data.Triggers = await _schedulerCenter.GetTaskStaus(data);
            return new MessageModel<SysTasksQz>()
            {
                msg = Resource_SysBase.OprateSuccess,
                success = true,
                data = data
            };
        }

        /// <summary>
        /// 添加计划任务
        /// </summary>
        /// <param name="tasksQz"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<string>> Add([FromBody] SysTasksQz tasksQz)
        {
            var data = new MessageModel<string>();
            _unitOfWork.BeginTran();
            tasksQz.CreateTime = DateTime.Now;
            tasksQz.UpdateTime = DateTime.Now;
            tasksQz.CreateBy = CurrentUser.LoginName;
            tasksQz.UpdateBy = CurrentUser.LoginName;
            tasksQz.RunTimes = 0;
            tasksQz.DelFlag = false;
            var id = await _tasksQzService.AddAsync(tasksQz);
            data.success = id > 0;
            try
            {
                if (data.success)
                {
                    tasksQz.ID = id;
                    data.data = id.ObjToString();
                    data.msg = "添加成功";
                    if ((bool)tasksQz.IsStart)
                    {
                        //如果是启动自动
                        var ResuleModel = await _schedulerCenter.AddScheduleJobAsync(tasksQz);
                        data.success = ResuleModel.success;
                        if (ResuleModel.success)
                        {
                            data.msg = $"{data.msg}=>启动成功=>{ResuleModel.msg}";
                        }
                        else
                        {
                            data.msg = $"{data.msg}=>启动失败=>{ResuleModel.msg}";
                        }
                    }
                }
                else
                {
                    data.msg = "添加失败";

                }
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                if (data.success)
                    _unitOfWork.CommitTran();
                else
                    _unitOfWork.RollbackTran();
            }
            return data;
        }

        /// <summary>
        /// 修改计划任务
        /// </summary>
        /// <param name="tasksQz"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<MessageModel<string>> Update([FromBody] SysTasksQz tasksQz)
        {
            var data = new MessageModel<string>();
            if (tasksQz != null && tasksQz.ID > 0)
            {
                _unitOfWork.BeginTran();
                tasksQz.UpdateBy = CurrentUser.LoginName;
                tasksQz.UpdateTime = DateTime.Now;
                data.success = await _tasksQzService.UpdateAsync(tasksQz);
                try
                {
                    if (data.success)
                    {
                        data.msg = "修改成功";
                        data.data = tasksQz?.ID.ObjToString();
                        if ((bool)tasksQz.IsStart)
                        {
                            var ResuleModelStop = await _schedulerCenter.StopScheduleJobAsync(tasksQz);
                            data.msg = $"{data.msg}=>停止:{ResuleModelStop.msg}";
                            var ResuleModelStar = await _schedulerCenter.AddScheduleJobAsync(tasksQz);
                            data.success = ResuleModelStar.success;
                            data.msg = $"{data.msg}=>启动:{ResuleModelStar.msg}";
                        }
                        else
                        {
                            var ResuleModelStop = await _schedulerCenter.StopScheduleJobAsync(tasksQz);
                            data.msg = $"{data.msg}=>停止:{ResuleModelStop.msg}";
                        }
                    }
                    else
                    {
                        data.msg = "修改失败";
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    if (data.success)
                        _unitOfWork.CommitTran();
                    else
                        _unitOfWork.RollbackTran();
                }
            }
            return data;
        }

        /// <summary>
        /// 删除一个任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<string>> Del(int jobId)
        {
            var data = new MessageModel<string>();

            var model = await _tasksQzService.QueryByIdAsync(jobId);
            if (model != null)
            {
                _unitOfWork.BeginTran();
                data.success = await _tasksQzService.DeleteAsync(model);
                try
                {
                    data.data = jobId.ObjToString();
                    if (data.success)
                    {
                        data.msg = "删除成功";
                        var ResuleModel = await _schedulerCenter.StopScheduleJobAsync(model);
                        data.msg = $"{data.msg}=>任务状态=>{ResuleModel.msg}";
                    }
                    else
                    {
                        data.msg = "删除失败";
                    }

                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    if (data.success)
                        _unitOfWork.CommitTran();
                    else
                        _unitOfWork.RollbackTran();
                }
            }
            else
            {
                data.msg = "任务不存在";
            }
            return data;

        }

        /// <summary>
        /// 启动计划任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<string>> StartJob(int jobId)
        {
            var data = new MessageModel<string>();

            var model = await _tasksQzService.QueryByIdAsync(jobId);
            if (model != null)
            {
                _unitOfWork.BeginTran();
                try
                {
                    model.UpdateBy = CurrentUser.LoginName;
                    model.UpdateTime = DateTime.Now;
                    model.IsStart = true;
                    data.success = await _tasksQzService.UpdateAsync(model);
                    data.data = jobId.ObjToString();
                    if (data.success)
                    {
                        data.msg = "更新成功";
                        var ResuleModel = await _schedulerCenter.AddScheduleJobAsync(model);
                        data.success = ResuleModel.success;
                        if (ResuleModel.success)
                        {
                            data.msg = $"{data.msg}=>启动成功=>{ResuleModel.msg}";

                        }
                        else
                        {
                            data.msg = $"{data.msg}=>启动失败=>{ResuleModel.msg}";
                        }
                    }
                    else
                    {
                        data.msg = "更新失败";
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    if (data.success)
                        _unitOfWork.CommitTran();
                    else
                        _unitOfWork.RollbackTran();
                }
            }
            else
            {
                data.msg = "任务不存在";
            }
            return data;
        }

        /// <summary>
        /// 停止一个计划任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>        
        [HttpGet]
        public async Task<MessageModel<string>> StopJob(int jobId)
        {
            var data = new MessageModel<string>();

            var model = await _tasksQzService.QueryByIdAsync(jobId);
            if (model != null)
            {
                model.UpdateBy = CurrentUser.LoginName;
                model.UpdateTime = DateTime.Now;
                model.IsStart = false;
                data.success = await _tasksQzService.UpdateAsync(model);
                data.data = jobId.ObjToString();
                if (data.success)
                {
                    data.msg = "更新成功";
                    var ResuleModel = await _schedulerCenter.StopScheduleJobAsync(model);
                    if (ResuleModel.success)
                    {
                        data.msg = $"{data.msg}=>停止成功=>{ResuleModel.msg}";
                    }
                    else
                    {
                        data.msg = $"{data.msg}=>停止失败=>{ResuleModel.msg}";
                    }
                }
                else
                {
                    data.msg = "更新失败";
                }
            }
            else
            {
                data.msg = "任务不存在";
            }
            return data;
        }

        /// <summary>
        /// 暂停一个计划任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>        
        [HttpGet]
        public async Task<MessageModel<string>> PauseJob(int jobId)
        {
            var data = new MessageModel<string>();
            var model = await _tasksQzService.QueryByIdAsync(jobId);
            if (model != null)
            {
                _unitOfWork.BeginTran();
                try
                {
                    data.success = await _tasksQzService.UpdateAsync(model);
                    data.data = jobId.ObjToString();
                    if (data.success)
                    {
                        data.msg = "更新成功";
                        var ResuleModel = await _schedulerCenter.PauseJob(model);
                        if (ResuleModel.success)
                        {
                            data.msg = $"{data.msg}=>暂停成功=>{ResuleModel.msg}";
                        }
                        else
                        {
                            data.msg = $"{data.msg}=>暂停失败=>{ResuleModel.msg}";
                        }
                        data.success = ResuleModel.success;
                    }
                    else
                    {
                        data.msg = "更新失败";
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    if (data.success)
                        _unitOfWork.CommitTran();
                    else
                        _unitOfWork.RollbackTran();
                }
            }
            else
            {
                data.msg = "任务不存在";
            }
            return data;
        }

        /// <summary>
        /// 恢复一个计划任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>        
        [HttpGet]
        public async Task<MessageModel<string>> ResumeJob(int jobId)
        {
            var data = new MessageModel<string>();

            var model = await _tasksQzService.QueryByIdAsync(jobId);
            if (model != null)
            {
                _unitOfWork.BeginTran();
                try
                {
                    model.IsStart = true;
                    data.success = await _tasksQzService.UpdateAsync(model);
                    data.data = jobId.ObjToString();
                    if (data.success)
                    {
                        data.msg = "更新成功";
                        var ResuleModel = await _schedulerCenter.ResumeJob(model);
                        if (ResuleModel.success)
                        {
                            data.msg = $"{data.msg}=>恢复成功=>{ResuleModel.msg}";
                        }
                        else
                        {
                            data.msg = $"{data.msg}=>恢复失败=>{ResuleModel.msg}";
                        }
                        data.success = ResuleModel.success;
                    }
                    else
                    {
                        data.msg = "更新失败";
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    if (data.success)
                        _unitOfWork.CommitTran();
                    else
                        _unitOfWork.RollbackTran();
                }
            }
            else
            {
                data.msg = "任务不存在";
            }
            return data;
        }

        /// <summary>
        /// 重启一个计划任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<string>> ReCovery(int jobId)
        {
            var data = new MessageModel<string>();
            var model = await _tasksQzService.QueryByIdAsync(jobId);
            if (model != null)
            {

                _unitOfWork.BeginTran();
                try
                {
                    model.UpdateBy = CurrentUser.LoginName;
                    model.UpdateTime = DateTime.Now;
                    model.IsStart = true;
                    data.success = await _tasksQzService.UpdateAsync(model);
                    data.data = jobId.ObjToString();
                    if (data.success)
                    {
                        data.msg = "更新成功";
                        var ResuleModelStop = await _schedulerCenter.StopScheduleJobAsync(model);
                        var ResuleModelStar = await _schedulerCenter.AddScheduleJobAsync(model);
                        if (ResuleModelStar.success)
                        {
                            data.msg = $"{data.msg}=>停止:{ResuleModelStop.msg}=>启动:{ResuleModelStar.msg}";
                            data.data = jobId.ObjToString();

                        }
                        else
                        {
                            data.msg = $"{data.msg}=>停止:{ResuleModelStop.msg}=>启动:{ResuleModelStar.msg}";
                            data.data = jobId.ObjToString();
                        }
                        data.success = ResuleModelStar.success;
                    }
                    else
                    {
                        data.msg = "更新失败";
                    }
                }
                catch (Exception)
                {
                    throw;
                }
                finally
                {
                    if (data.success)
                        _unitOfWork.CommitTran();
                    else
                        _unitOfWork.RollbackTran();
                }
            }
            else
            {
                data.msg = "任务不存在";
            }
            return data;

        }

        /// <summary>
        /// 获取任务命名空间
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public MessageModel<List<QuartzReflectionView>> GetTaskNameSpace()
        {
            var baseType = typeof(IJob);
            var path = AppDomain.CurrentDomain.RelativeSearchPath ?? AppDomain.CurrentDomain.BaseDirectory;
            var referencedAssemblies = System.IO.Directory.GetFiles(path, "Admin.Core.Tasks.dll").Select(Assembly.LoadFrom).ToArray();
            var types = referencedAssemblies
                .SelectMany(a => a.DefinedTypes)
                .Select(type => type.AsType())
                .Where(x => x != baseType && baseType.IsAssignableFrom(x)).ToArray();
            var implementTypes = types.Where(x => x.IsClass).Select(item => new QuartzReflectionView { nameSpace = item.Namespace, nameClass = item.Name, remark = "" }).ToList();
            return MessageModel<List<QuartzReflectionView>>.Success("获取成功", implementTypes);
        }

        /// <summary>
        /// 立即执行任务
        /// </summary>
        /// <param name="jobId"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<MessageModel<string>> ExecuteJob(int jobId)
        {
            var data = new MessageModel<string>();

            var model = await _tasksQzService.QueryByIdAsync(jobId);
            if (model != null)
            {
                return await _schedulerCenter.ExecuteJobAsync(model);
            }
            else
            {
                data.success = false;
                data.msg = "任务不存在";
            }
            return data;
        }

    }
}