//#define AYSHOWKPIQUERYINFO

using Sockeye.Biz;
using Newtonsoft.Json.Linq;
using Microsoft.Extensions.Logging;
using Sockeye.Models;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;

namespace Sockeye.KPI
{
    internal static class KPIFetcher
    {

#if (AYSHOWKPIQUERYINFO)
#if (DEBUG)
#warning FYI AYSHOWKPIQUERYINFO is defined
#else
#error ### HOLDUP: AYSHOWKPIQUERYINFO is defined in a RELEASE BUILD!!!!
#endif
#endif

        //case 4200
        //### WARNING: IF CHANGE HERE **must** update CLIENT dash-base.js same named constant as it relies on it's own copy of this CONSTANT value to indicate if there are possibly more
        internal const int KPI_LIST_MAX_ITEMS_TO_RETURN = 100;//Maximum number of items to return from a KPI dashboard query so as not to overwhelm the client with too much data

        ////////////////////////////////////////////////
        // Get the kpi data requested
        //
        //
        internal static async Task<JObject> GetResponseAsync(AyContext ct, KPIRequestOptions options, AuthorizationRoles userRoles, ILogger log, long userId)
        {

            /*
            return a jobject like:
            {
                error: "if error this key present",
                meta: {username:"joe blow","date range:blah to blah"}
                data:[{r1},{r2},{r3}]
            }
            */
            //instantiate the list
            var kpi = KPIFactory.GetAyaKPI(options.KPIName);

            if (!Sockeye.Api.ControllerHelpers.Authorized.HasAnyRole(userRoles, kpi.AllowedRoles))
            {
                return JObject.FromObject(new
                {
                    error = "NOT AUTHORIZED"
                });
            }

            kpi.BuildQuery(options, userId);

            if (!string.IsNullOrWhiteSpace(kpi.ErrorMessage))
            {
                return JObject.FromObject(new
                {
                    error = kpi.ErrorMessage
                });
            }


            JArray jData = new JArray();
            JArray jMeta = new JArray();

#if (DEBUG && AYSHOWKPIQUERYINFO)
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();

#endif
            //QUERY THE DB
            using (var command = ct.Database.GetDbConnection().CreateCommand())
            {
                await ct.Database.OpenConnectionAsync();

                //GET DATA RETURN ROWS
                command.CommandText = kpi.DataQuery;
                try
                {
#if (DEBUG && AYSHOWKPIQUERYINFO)
                    stopWatch.Start();
#endif
                    using (var dr = await command.ExecuteReaderAsync())
                    {
#if (DEBUG && AYSHOWKPIQUERYINFO)
                        stopWatch.Stop();
                        log.LogInformation($"(debug) KPIFetcher:GetResponse DATA query took {stopWatch.ElapsedMilliseconds}ms to execute: {kpi.DataQuery}");
                        stopWatch.Reset();
#endif

                        while (dr.Read())
                        {
                            //only one column and it's the zeroth json string column
                            if (!dr.IsDBNull(0))
                                jData.Add(JObject.Parse(dr.GetString(0)));
                        }
                    }

                    if (!string.IsNullOrWhiteSpace(kpi.MetaQuery))
                    {
                        //GET META DATA ROWS
                        command.CommandText = kpi.MetaQuery;
#if (DEBUG && AYSHOWQUERYINFO)
                    stopWatch.Start();
#endif
                        using (var dr = await command.ExecuteReaderAsync())
                        {
#if (DEBUG && AYSHOWQUERYINFO)
                        stopWatch.Stop();
                        log.LogInformation($"(debug) KPIFetcher:GetResponse META query took {stopWatch.ElapsedMilliseconds}ms to execute: {qTotalRecordsQuery}");
#endif
                            while (dr.Read())
                            {
                                //only one column and it's the zeroth json string column
                                if (!dr.IsDBNull(0))
                                    jMeta.Add(JObject.Parse(dr.GetString(0)));
                            }
                        }
                    }
                }
                catch (Npgsql.PostgresException e)
                {
                    //log out the exception and the query
                    log.LogError("KPIFetcher:GetResponseAsync query failed.  Data Query was:");
                    log.LogError(kpi.DataQuery);
                    log.LogError("Meta Query was:");
                    log.LogError(kpi.MetaQuery);
                    log.LogError(e, "DB Exception");
                    throw new System.Exception("KPIFetcher:GetResponseAsync - Query failed see log");

                }
                catch (System.Exception e)
                {
                    //ensure any other type of exception gets surfaced properly
                    //log out the exception and the query
                    log.LogError("KPIFetcher:GetResponseAsync unexpected failure.  Data Query was:");
                    log.LogError(kpi.DataQuery);
                    log.LogError("Meta Query was:");
                    log.LogError(kpi.MetaQuery);
                    log.LogError(e, "Exception");
                    throw new System.Exception("KPIFetcher:GetResponseAsync - unexpected failure see log");
                }


                return JObject.FromObject(new
                {
                    meta = jMeta,
                    data = jData
                });

            }
        }




    }//eoc
}//eons