using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.Extensions.Logging;
using App.Metrics;
using AyaNova.Util;
using AyaNova.Models;



namespace AyaNova.Biz
{


    /// <summary>
    /// called by Generator to gather server metrics and check on things
    /// See MetricsRegistry for defined metrics 
    /// 
    /// </summary>
    internal static class CoreJobMetricsSnapshot
    {
        private static ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("CoreJobMetricsSnapshot");

#if (DEBUG)
        private static TimeSpan DO_EVERY_INTERVAL = new TimeSpan(0, 1, 0);//DEBUG do a check every 60 seconds
#else
        private static TimeSpan DO_EVERY_INTERVAL = new TimeSpan(0, 15, 0);//RELEASE do a check every 15 minutes
#endif

        private static DateTime lastServerCheckDone = DateTime.MinValue;
        private static DateTime lastRecordCountCheck = DateTime.MinValue;
        private static DateTime lastFileCountCheck = DateTime.MinValue;

        ////////////////////////////////////////////////////////////////////////////////////////////////
        // DoAsync
        //
        public static async Task DoJobAsync(AyContext ct)
        {
            //https://www.app-metrics.io/
            IMetrics metrics = (IMetrics)ServiceProviderProvider.Provider.GetService(typeof(IMetrics));

            //This will get triggered roughly every minute (10 seconds in debug), but we don't want to healthcheck that frequently
            if (!DateUtil.IsAfterDuration(lastServerCheckDone, DO_EVERY_INTERVAL))
                return;

            log.LogTrace("Starting metrics snapshot");

            //Gather core metrics here
            var process = Process.GetCurrentProcess();

            //PHYSICAL MEMORY
            metrics.Measure.Gauge.SetValue(MetricsRegistry.PhysicalMemoryGauge, process.WorkingSet64);

            //PRIVATE BYTES
            metrics.Measure.Gauge.SetValue(MetricsRegistry.PrivateBytesGauge, process.PrivateMemorySize64);

            //RECORDS IN TABLE
            //Only do this once per hour
            if (DateUtil.IsAfterDuration(lastRecordCountCheck, 1))
            {
                lastRecordCountCheck = DateTime.UtcNow;
                log.LogTrace("Counting table records");


                //Get a count of important tables in db
                List<string> allTableNames = await DbUtil.GetAllTablenamesAsync();

                //Skip some tables as they are internal and / or only ever have one record
                List<string> skipTableNames = new List<string>();
                skipTableNames.Add("alicense");
                skipTableNames.Add("aschemaversion");

                foreach (string table in allTableNames)
                {
                    if (!skipTableNames.Contains(table))
                    {
                        var tags = new MetricTags("TableTagKey", table);
                        metrics.Measure.Gauge.SetValue(MetricsRegistry.DBRecordsGauge, tags, await DbUtil.CountOfRecordsAsync(table));
                    }
                }
            }

            //JOB COUNTS (DEAD, RUNNING, COMPLETED, SLEEPING)

            foreach (JobStatus stat in Enum.GetValues(typeof(JobStatus)))
            {
                var jobtag = new MetricTags("JobStatus", stat.ToString());
                metrics.Measure.Gauge.SetValue(MetricsRegistry.JobsGauge, jobtag, await JobsBiz.GetCountForJobStatusAsync(ct, stat));
            }



            //FILES ON DISK
            //Only do this once per hour
            if (DateUtil.IsAfterDuration(lastFileCountCheck, 1))
            {
                lastFileCountCheck = DateTime.UtcNow;
                log.LogTrace("Files on disk information");
                var UtilFilesInfo = FileUtil.GetUtilityFolderSizeInfo();
                var UserFilesInfo = FileUtil.GetAttachmentFolderSizeInfo();

                var mtag = new MetricTags("File type", "Business object files");
                metrics.Measure.Gauge.SetValue(MetricsRegistry.FileCountGauge, mtag, UserFilesInfo.FileCountWithChildren);
                metrics.Measure.Gauge.SetValue(MetricsRegistry.FileSizeGauge, mtag, UserFilesInfo.SizeWithChildren);

                mtag = new MetricTags("File type", "OPS files");
                metrics.Measure.Gauge.SetValue(MetricsRegistry.FileCountGauge, mtag, UtilFilesInfo.FileCountWithChildren);
                metrics.Measure.Gauge.SetValue(MetricsRegistry.FileSizeGauge, mtag, UtilFilesInfo.SizeWithChildren);

            }


            lastServerCheckDone = DateTime.UtcNow;


            //just to hide compiler warning for now
            await Task.CompletedTask;

        }





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

    }//eoc


}//eons

