using System.Data;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration;
using Hims.Shared.EntityModels;
using Hims.Shared.UserModels.Filters;

namespace Hims.Infrastructure.Services
{
    using Hims.Domain.Services;
    using System;
    using Dapper;
    using Hims.Domain.Repositories.UnitOfWork;
    using System.Collections.Generic;
    using Npgsql;


    /// <inheritdoc />
    public class ExceptionLogServices : IExceptionLogService
    {
        /// <summary>
        /// The unit of work.
        /// </summary>
        private readonly IUnitOfWork unitOfWork;

        /// <summary>
        /// The connection name.
        /// </summary>
        private readonly string Connection;

        /// <inheritdoc />
        public ExceptionLogServices(IUnitOfWork unitOfWork, IConfiguration configuration)
        {
            this.unitOfWork = unitOfWork;

            if (configuration.GetConnectionString($"Connection") != null)
            {
                this.Connection = configuration.GetConnectionString($"Connection");
            }
        }

        /// <inheritdoc />
        public void Invoke(string logFrom, string logRoute, string errorMessage, string errorDescription)
        {
            try
            {
                using (NpgsqlConnection connection = new NpgsqlConnection(Connection))
                {
                    if (connection.State == ConnectionState.Closed)
                    {
                        connection.Open();
                    }

                    string query = $@"INSERT INTO ""ExceptionLog"" (""LogFrom"", ""LogRoute"", ""Message"", ""Description"", ""LogDate"", ""LogTime"", ""LogTimestamp"", ""Active"" ) VALUES ('{logFrom}', '{logRoute}', '{errorMessage}','{errorDescription}','{DateTime.UtcNow}'::date,'{DateTime.UtcNow}'::time,'{DateTime.UtcNow}', true);";
                    NpgsqlCommand command = new NpgsqlCommand(query, connection);
                    command.ExecuteNonQuery();
                }
            }
            catch (Exception)
            {
                //ignore
            }
        }

        /// <inheritdoc />
        public async Task<IEnumerable<ExceptionLogModel>> FetchAsync(ExceptionLogFilterModel model)
        {
            var where = $@" WHERE 1 = 1 ";
           
            if (model.LogPath!=null)
            {
                where += $@" AND split_part(""LogRoute"", '/', 2) = '{model.LogPath}'";
            }
            if (model.LogPathMethod != null)
            {
                where += $@" AND split_part(""LogRoute"", '/', 3) = '{model.LogPathMethod}'";
            }
            if (!string.IsNullOrEmpty(model.FromDate) && !string.IsNullOrEmpty(model.ToDate))
            {
                where += $@" AND (""LogDate"" at time zone 'UTC' at time zone 'Asia/Kolkata')::DATE >= '{model.FromDate}'::DATE";
                where += $@" AND (""LogDate"" at time zone 'UTC' at time zone 'Asia/Kolkata')::DATE <= '{model.ToDate}'::DATE"; 
            }

            var query = $@"SELECT COUNT(*) OVER() AS ""TotalItems"", ""ExceptionLogId"", ""LogFrom"", ""LogRoute"", ""LogDate"", ""LogTime"", ""LogTimestamp"", ""Message"", ""Description"", ""Active""  FROM ""ExceptionLog""
                        {where} Order by ""ExceptionLogId"" DESC";

            if (model.PageIndex <= 0)
            {
                return await this.unitOfWork.Current.QueryAsync<ExceptionLogModel>(query);
            }

            model.PageIndex -= 1;
            query += " LIMIT " + model.PageSize + " offset " + (model.PageIndex * model.PageSize);
            return await this.unitOfWork.Current.QueryAsync<ExceptionLogModel>(query);
        }

        /// <inheritdoc />
        public async Task<int> ResolveAsync(int exceptionLogId)
        {
            string query = $@"UPDATE ""ExceptionLog"" SET ""Active""= false WHERE ""ExceptionLogId"" = {exceptionLogId} ";
            return await this.unitOfWork.Current.ExecuteAsync(query);
        }
        /// <inheritdoc />GetMethodAsync
        public async Task<IEnumerable<ExceptionLogModel>> GetMethodAsync(string model)
        {
            //'api/appointments%
            string query = $@"select distinct split_part(""LogRoute"", '/', 3) AS ""LogPathMethod"" from ""ExceptionLog"" where ""LogRoute"" ILike  'api/{model}%'";
            return await this.unitOfWork.Current.QueryAsync<ExceptionLogModel>(query);
        }

        ///// <inheritdoc />
        public async Task<IEnumerable<ExceptionLogModel>> GetLogRouteAsync()
        {
            string query = $@"select distinct split_part(""LogRoute"", '/', 2) AS ""LogPath"" from ""ExceptionLog""";
            return await this.unitOfWork.Current.QueryAsync<ExceptionLogModel>(query);
        }


    }
}