using Dapper;
using EVCB_OCPP.Domain;
using EVCB_OCPP.WEBAPI.Helpers;
using EVCB_OCPP.WEBAPI.Models.WebAPI.Dto;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Threading.Tasks;

namespace EVCB_OCPP.WEBAPI.Services
{
    public class MainDbService
    {
        public MainDbService(
            SqlConnectionFactory<MainDBContext> mainDbConneciotnFactory,
            IMemoryCache memoryCache,
            ILogger<MainDbService> logger)
        {
            this.memoryCache = memoryCache;
            this.logger = logger;
            this.mainDbConneciotnFactory = mainDbConneciotnFactory;
        }

        private readonly SqlConnectionFactory<MainDBContext> mainDbConneciotnFactory;
        private readonly IMemoryCache memoryCache;
        private readonly ILogger<MainDbService> logger;

        public async ValueTask<bool> ContainsChargePointAsync(string chargeBoxId, string customerId)
        {
            bool existed = false;

            if (string.IsNullOrEmpty(chargeBoxId)) return existed;

            var parameters = new DynamicParameters();
            parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
            parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input, 36);


            using (SqlConnection conn = await mainDbConneciotnFactory.CreateAsync())
            {
                string strSql = "Select COUNT(1) from [dbo].[Machine] where ChargeBoxId=@ChargeBoxId and CustomerId=@CustomerId  and IsDelete=0; ";
                existed = await conn.ExecuteScalarAsync<bool>(strSql, parameters, null, EVCBConfiguration.DB_DefaultConnectionTimeout);
            }

            return existed;
        }

        internal async Task<List<TransasctionData>> GetActiveTransactionAsync(string chargeBoxId,string customerId, int? sessionId, string idTag)
        {
            var toReturn = new List<TransasctionData>();
            try
            {
                var parameters = new DynamicParameters();
                parameters.Add("@CustomerId", customerId, DbType.String, ParameterDirection.Input, 50);
                parameters.Add("@ChargeBoxId", chargeBoxId, DbType.String, ParameterDirection.Input, 50);
                parameters.Add("@StartIdTag",idTag, DbType.String, ParameterDirection.Input, 20);
                parameters.Add("@Id", sessionId is null ? 0 : sessionId.Value, DbType.Int32, ParameterDirection.Input, 20);

                string date = DateTime.UtcNow.ToString("yyMMdd");
                //string strSql = string.Empty;
                var cmd = CreateGetActiveTransactionCmd(customerId, sessionId, idTag);

                using SqlConnection conn = await mainDbConneciotnFactory.CreateAsync();
                toReturn = (await conn.QueryAsync<TransasctionData>(cmd, parameters, commandTimeout: EVCBConfiguration.DB_DefaultConnectionTimeout)).ToList();

            }
            catch (Exception ex)
            {
                logger.LogError(ex.Message);
                logger.LogError(ex.StackTrace);
            }

            return toReturn;
        }

        private string CreateGetActiveTransactionCmd(string customerId, int? sessionId, string idTag)
        {
            string cmdBase = """
                    WITH CTE AS (
                        SELECT
                            Id, ConnectorId, StartTime, Fee, StartIdTag,
                            ROW_NUMBER() OVER (PARTITION BY s.ConnectorId ORDER BY s.StartTime DESC) AS RowNum
                        FROM [dbo].[TransactionRecord] s
                        WHERE StopTime = '1991-01-01 00:00:00.000' AND ChargeBoxId = @ChargeBoxId
                            AND StopTransactionReportedOn = '1991-01-01 00:00:00.000'
                            {0}
                    )
                    SELECT Id, ConnectorId, StartTime, Fee, StartIdTag
                    FROM CTE
                    WHERE RowNum = 1;
                    """;
            string param = string.Empty;

            if (!string.IsNullOrEmpty(customerId))
            {
                param += ("AND CustomerId = @CustomerId ");
            }

            if (!string.IsNullOrEmpty(idTag))
            {
                param += ("AND StartIdTag = @StartIdTag ");
            }

            if (sessionId is not null)
            {
                param += ("AND Id = @Id ");
            }

            return string.Format(cmdBase, param);
        }
    }
}
