using System;
using System.Linq;
using System.Threading.Tasks;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using AyaNova.Models;


namespace AyaNova.Biz
{


    internal class JobOperationsBiz : BizObject, IJobObject
    {

        internal JobOperationsBiz(AyContext dbcontext, long currentUserId, AuthorizationRoles userRoles)
        {
            ct = dbcontext;
            UserId = currentUserId;
            CurrentUserRoles = userRoles;
            BizType = AyaType.ServerJob;
        }



        ////////////////////////////////////////////////////////////////////////////////////////////////
        // GET
        //        
        internal async Task<List<JobOperationsFetchInfo>> GetJobListAsync()
        {
            List<JobOperationsFetchInfo> ret = new List<JobOperationsFetchInfo>();

            var jobitems = await ct.OpsJob
                            .OrderBy(z => z.Created)
                           .ToListAsync();

            foreach (OpsJob i in jobitems)
            {
                //fetch the most recent log time for each job 
                var mostRecentLogItem = await ct.OpsJobLog
                .Where(z => z.JobId == i.GId)
                .OrderByDescending(z => z.Created)
                .FirstOrDefaultAsync();

                JobOperationsFetchInfo o = new JobOperationsFetchInfo();
                if (mostRecentLogItem != null)
                    o.LastAction = mostRecentLogItem.Created;
                else
                    o.LastAction = i.Created;

                o.Created = i.Created;
                o.GId = i.GId;
                o.JobStatus = i.JobStatus.ToString();
                o.Name = i.Name;
                ret.Add(o);
            }

            return ret;
        }



        //Get list of logs for job
        internal async Task<List<JobOperationsLogInfoItem>> GetJobLogListAsync(Guid jobId)
        {
            List<JobOperationsLogInfoItem> ret = new List<JobOperationsLogInfoItem>();

            var l = await ct.OpsJobLog
                            .Where(z => z.JobId == jobId)
                            .OrderBy(z => z.Created)
                            .ToListAsync();

            foreach (OpsJobLog i in l)
            {

                JobOperationsLogInfoItem o = new JobOperationsLogInfoItem();

                o.Created = i.Created;
                o.StatusText = i.StatusText;
                ret.Add(o);
            }

            return ret;
        }


        ///////////////////////////////////////////////////////////////////////////////
        //GET LOG OF ALL JOBS FOR CLIENT
        //
        internal async Task<List<JobOperationsLogInfoItem>> GetAllJobsLogsListAsync()
        {
            List<JobOperationsLogInfoItem> ret = new List<JobOperationsLogInfoItem>();
            var l = await ct.OpsJobLog
                            .OrderByDescending(z => z.Created)
                            .ToListAsync();
            foreach (OpsJobLog i in l)
            {
                JobOperationsLogInfoItem o = new JobOperationsLogInfoItem();
                o.Created = i.Created;
                o.StatusText = i.StatusText;
                o.JobId = i.JobId;
                ret.Add(o);
            }
            return ret;
        }



        ////////////////////////////////////////////////////////////////////////////////////////////////
        //JOB / OPERATIONS
        //
        public async Task HandleJobAsync(OpsJob job)
        {
            //Hand off the particular job to the corresponding processing code
            //NOTE: If this code throws an exception the caller (JobsBiz::ProcessJobsAsync) will automatically set the job to failed and log the exeption so 
            //basically any error condition during job processing should throw up an exception if it can't be handled
            switch (job.JobType)
            {

                case JobType.TestJob:
                    await ProcessTestJobAsync(job);
                    break;
                default:
                    throw new System.ArgumentOutOfRangeException($"JobOperationsBiz.HandleJob-> Invalid job type{job.JobType.ToString()}");
            }
        }

        private async Task ProcessTestJobAsync(OpsJob job)
        {
            var sleepTime = 30 * 1000;
            await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Running);
            await JobsBiz.LogJobAsync(job.GId, $"Test job started, sleeping for {sleepTime/1000} seconds...");
            await Task.Delay(sleepTime);
            await JobsBiz.LogJobAsync(job.GId, "Test job done sleeping setting status to finished");
            await JobsBiz.UpdateJobStatusAsync(job.GId, JobStatus.Completed);
        }



        /////////////////////////////////////////////////////////////////////

    }//eoc


}//eons

