using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using MegaRobo.Logger;

namespace MegaRobo.RRQuartz;

internal class JobManager
{
    public JobManager()
    {
    }

    private Thread _threadLoop;

    public bool IsStop { get; private set; } = true;
    public ILogger Logger { get; init; }
    public TimeSpan LoopInterval { get; set; } = TimeSpan.FromMilliseconds(500);

    public event EventHandler<JobItemBase> TryCountMoreEvent;
    public event EventHandler<JobItemBase> JobItemChangedEvent;

    public void Start()
    {
        this.IsStop = false;
        if(this._threadLoop is not null) return;
        this._threadLoop = new Thread(this.ThreadLoop) { IsBackground = true, Name = nameof(JobManager) + "_" + Guid.NewGuid().ToString("N") };
        this._threadLoop.Start();
        this.CurrentJob?.UsedTime.Start();
        this.Logger?.LogInformation("已启动..");
    }

    public void Stop()
    {
        this.IsStop = true;
        this.CurrentJob?.Stop();
        this.Logger?.LogInformation("已暂停.");
    }

    public JobItemBase CurrentJob { get; private set; }

    public void Add(JobItemBase item)
    {
        this.Logger.LogDebug($"新增JobItem:{item.Name} Guid:{item.Guid}");
        this.JobPool.Add(item);
    }

    public IList<JobItemBase> JobPool { get; private set; } = new List<JobItemBase>();


    public void RemoveJobByGroupName(string groupName)
    {
        this.JobPool = this.JobPool.Where(x => x.GroupName != groupName).ToList();
    }

    public void ClearJob(string desc)
    {
        this.Logger.LogInformation($"清理计划任何.∵{desc}");
        this.JobPool.Clear();
        this.CurrentJob = null;
    }

    public string GetRunWarnText()
    {
        if(this.IsStop)
            return "暂停中..";
        if(this._threadLoop == null)
            return "未启动";
        if(this.CurrentJob == null)
            return "等待新任务";
        if(this.CurrentJob.ExecCount > this.CurrentJob.TryCount)
            return "执行超时";
        return null;
    }

    private void ThreadLoop()
    {
        while(!this.IsStop)
        {
            try
            {
                this.RunLoopStep();
            } catch(Exception ex)
            {
                Console.WriteLine(ex);
            } finally
            {
                Thread.Sleep(this.LoopInterval);
            }
        }
        this._threadLoop = null;
    }

    private async void RunLoopStep()
    {
        if(this.IsStop)
            return;

        if(this.CurrentJob != null)
        {
            if(this.CurrentJob.Status == JobStatus.RunSuccess)
            {
                this.Logger?.LogDebug($"移除已执行Job:{this.CurrentJob.Title} Guid:{this.CurrentJob.Guid}");
                this.CurrentJob = null;
            } else if(this.CurrentJob.Status == JobStatus.RunFailed)
            {

            } else if(this.CurrentJob.ExecCount > 0 && !this.CurrentJob.CheckTimeout())
            {
                //未超时，可能还在执行中或者等待结果回应
                // this.JobItemChangedEvent?.Invoke(this, this.CurrentJob);
                return;
            }
        }
        if(this.CurrentJob is null)
        {
            this.CurrentJob = this.JobPool.FirstOrDefault(x => !CheckIsFinish(x.Status));
            this.JobItemChangedEvent?.Invoke(this, this.CurrentJob);
            if(this.CurrentJob is null)
            {
                return;
            } else
            {
                this.Logger?.LogDebug($"获取新任务:{this.CurrentJob.Title} Guid:{this.CurrentJob.Guid}");
            }
        }
        if(this.CurrentJob.ExecCount >= this.CurrentJob.TryCount && this.CurrentJob.TryCount > 0)
        {
            if(this.CurrentJob.ExecCount == this.CurrentJob.TryCount)
            {
                this.CurrentJob.ExecCount++;
                this.TryCountMoreEvent?.Invoke(this, null);
            }
        } else if((this.CurrentJob.Status == JobStatus.RunFailed || this.CurrentJob.CheckTimeout()) && this.CurrentJob.TryCount > 0)
        {
            this.Logger?.LogInformation($"执行Job,Name: {this.CurrentJob.Title} Guid:{this.CurrentJob.Guid}失败或超时,正在进行第{this.CurrentJob.ExecCount + 1}/{this.CurrentJob.TryCount}重试");
            Task task = this.CurrentJob.OnExecuteActionAsync();
            task.Wait();
            if(this.CurrentJob != null)
            {
                this.Logger?.LogDebug($"已执行Job,Name: {this.CurrentJob.Title} Guid:{this.CurrentJob.Guid}");
            }
        } else if(this.CurrentJob.Status == JobStatus.None || this.CurrentJob.TryCount < 0)
        {
            this.Logger?.LogInformation($"准备执行Job,Name: {this.CurrentJob.Title} Guid:{this.CurrentJob.Guid}");
            Task task = this.CurrentJob.OnExecuteActionAsync();
            task.Wait();
            this.Logger?.LogDebug($"已执行Job,Name: {this.CurrentJob?.Title} Guid:{this.CurrentJob?.Guid}");
        }

        bool CheckIsFinish(JobStatus jobStatus)
        {
            return jobStatus is JobStatus.RunFailed or JobStatus.RunSuccess;
        }
    }
}