using EVCB_OCPP.Domain;
using EVCB_OCPP.Domain.Models.MainDb;
using EVCB_OCPP.Packet.Features;
using EVCB_OCPP.Packet.Messages;
using EVCB_OCPP.Packet.Messages.SmartCharging;
using EVCB_OCPP.Packet.Messages.SubTypes;
using EVCB_OCPP.WSServer.Service.WsService;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace EVCB_OCPP.WSServer.Message
{
    internal partial class ProfileHandler
    {


        internal async void SetChargingProfile(string chargeBoxId, decimal value, ChargingRateUnitType unit)
        {
            var _setProfileRequest = new SetChargingProfileRequest()
            {
                connectorId = 0,
                csChargingProfiles = new Packet.Messages.SubTypes.csChargingProfiles()
                {
                    chargingProfileId = 1,
                    chargingProfileKind = Packet.Messages.SubTypes.ChargingProfileKindType.Recurring,
                    chargingProfilePurpose = Packet.Messages.SubTypes.ChargingProfilePurposeType.ChargePointMaxProfile,
                    chargingSchedule = new Packet.Messages.SubTypes.ChargingSchedule()
                    {
                        chargingRateUnit = unit,
                        chargingSchedulePeriod = new List<Packet.Messages.SubTypes.ChargingSchedulePeriod>()
                                                    {
                                                        new Packet.Messages.SubTypes.ChargingSchedulePeriod(){  startPeriod=0, limit=value}
                                                    },
                        duration = 86400,

                    },
                    recurrencyKind = Packet.Messages.SubTypes.RecurrencyKindType.Daily,
                    stackLevel = 1,

                }
            };

            await mainDbService.AddServerMessage(
                ChargeBoxId: chargeBoxId,
                OutAction: _setProfileRequest.Action.ToString(),
                OutRequest: _setProfileRequest
                );
        }


        internal async void ClearChargingProfile(string chargeBoxId)
        {
            var _clearProfileRequest = new ClearChargingProfileRequest()
            {
                connectorId = 0,
                chargingProfilePurpose = ChargingProfilePurposeType.ChargePointMaxProfile,

            };

            await mainDbService.AddServerMessage(new ServerMessage()
            {
                ChargeBoxId = chargeBoxId,
                OutAction = _clearProfileRequest.Action.ToString(),
                OutRequest = JsonConvert.SerializeObject(_clearProfileRequest, new JsonSerializerSettings() { NullValueHandling = NullValueHandling.Ignore, Formatting = Formatting.None })
            });
        }

        internal async Task<MessageResult> ExecuteSmartChargingConfirm(Actions action, WsClientData session, IConfirmation confirm, string requestId)
        {
            MessageResult result = new MessageResult() { Success = true };

            switch (action)
            {
                case Actions.ClearChargingProfile:

                    {
                        ClearChargingProfileConfirmation _confirm = confirm as ClearChargingProfileConfirmation;
                        ClearChargingProfileRequest _request = _confirm.GetRequest() as ClearChargingProfileRequest;
                        using (var db = await maindbContextFactory.CreateDbContextAsync())
                        {
                            var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync();
                            if (operation != null)
                            {
                                operation.FinishedOn = DateTime.UtcNow;
                                operation.Status = 1;//電樁有回覆
                                operation.EvseStatus = (int)_confirm.status;//OK
                                operation.EvseValue = _confirm.status.ToString();
                                await db.SaveChangesAsync();
                            }

                        }
                    }
                    break;
                case Actions.SetChargingProfile:
                    {
                        SetChargingProfileConfirmation _confirm = confirm as SetChargingProfileConfirmation;
                        SetChargingProfileRequest _request = _confirm.GetRequest() as SetChargingProfileRequest;
                        using (var db = await maindbContextFactory.CreateDbContextAsync())
                        {
                            var operation = await db.MachineOperateRecord.Where(x => x.SerialNo == requestId &&
                            x.ChargeBoxId == session.ChargeBoxId && x.Status == 0).FirstOrDefaultAsync();
                            if (operation != null)
                            {
                                operation.FinishedOn = DateTime.UtcNow;
                                operation.Status = 1;//電樁有回覆
                                operation.EvseStatus = (int)_confirm.status;//OK
                                operation.EvseValue = _confirm.status.ToString();
                                await db.SaveChangesAsync();
                            }

                        }
                    }
                    break;
                case Actions.GetCompositeSchedule:
                    {
                        GetCompositeScheduleConfirmation _confirm = confirm as GetCompositeScheduleConfirmation;
                        GetCompositeScheduleRequest _request = _confirm.GetRequest() as GetCompositeScheduleRequest;
                        using (var db = await maindbContextFactory.CreateDbContextAsync())
                        {
                            var operation = await db.MachineOperateRecord
                                .Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0)
                                .FirstOrDefaultAsync();
                            if (operation != null)
                            {
                                operation.FinishedOn = DateTime.UtcNow;
                                operation.Status = 1;//電樁有回覆
                                operation.EvseStatus = (int)_confirm.status;//OK
                                operation.EvseValue = JsonConvert.SerializeObject(_confirm.chargingSchedule, Formatting.None);
                                await db.SaveChangesAsync();
                            }

                        }
                    }
                    break;
                default:
                    {
                        logger.LogWarning(string.Format("Not Implement {0} Logic", confirm.GetType().ToString().Replace("OCPPPackage.Messages.RemoteTrigger.", "")));
                    }
                    break;
            }
            return result;
        }


        internal async Task<MessageResult> ReceivedSmartChargingError(Actions action, string errorMsg, WsClientData session, string requestId)
        {
            MessageResult result = new MessageResult() { Success = true };

            switch (action)
            {
                case Actions.ClearChargingProfile:
                case Actions.SetChargingProfile:
                case Actions.GetCompositeSchedule:
                    {
                        using (var db = await maindbContextFactory.CreateDbContextAsync())
                        {
                            var operation = await db.MachineOperateRecord
                                .Where(x => x.SerialNo == requestId && x.ChargeBoxId == session.ChargeBoxId && x.Status == 0)
                                .FirstOrDefaultAsync();
                            if (operation != null)
                            {
                                operation.FinishedOn = DateTime.UtcNow;
                                operation.Status = 1;//電樁有回覆
                                operation.EvseStatus = (int)255;//錯誤
                                operation.EvseValue = errorMsg;
                                await db.SaveChangesAsync();
                            }

                        }
                    }
                    break;

                default:
                    {
                        logger.LogWarning(string.Format("Not Implement {0} Logic", action));
                    }
                    break;
            }
            return result;

        }
    }
}