using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.Localization;
using MS.Common.IDCode;
using MS.Component.Jwt.UserClaim;
using MS.DbContexts;
using MS.Entities.AccountingService_Models;
using MS.Entities.AuthService_Models;
using MS.Entities.Models;
using MS.Models;
using MS.UnitOfWork;
using MS.WebCore.Core;
using Newtonsoft.Json;
using NLog;
using NPOI.SS.Formula.Functions;
using Org.BouncyCastle.Tsp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;

namespace MS.Services.PosTrxService
{
    public class PosTrxLineItemsService : BaseService, IPosTrxLineItemsService
    {
        Expression<Func<PosTrxLineItems, bool>> whereClause;
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly JsonSerializerOptions _jsonSerializerOptions;
        Logger logger = LogManager.GetCurrentClassLogger();
        public PosTrxLineItemsService(IUnitOfWork<MSDbContext> unitOfWork, IMapper mapper, IdWorker idWorker, IClaimsAccessor claimsAccessor, IStringLocalizer localizer, IHttpContextAccessor httpContextAccessor, IUnitOfWork<AccountingContext> AccountingContext, IUnitOfWork<SQLiteContext> SQLiteContext, IUnitOfWork<AuthContext> AuthContext) : base(unitOfWork, mapper, idWorker, claimsAccessor, localizer, AccountingContext, SQLiteContext, AuthContext)
        {
            _httpContextAccessor = httpContextAccessor;
            _jsonSerializerOptions = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true // 根据需要进行配置
            };
        }
        public async Task<ExecuteResult> fixFuelItemTagAsync(string startTime)
        {

            DateTime dateTime = string.IsNullOrEmpty(startTime) ? DateTime.Now : DateTime.Parse(startTime);
            DateTime enddateTime = string.IsNullOrEmpty(startTime) ? DateTime.Now.AddDays(-2) : DateTime.Parse(startTime).AddDays(-2);
            //            var query = _unitOfWork.GetRepository<PosTrxes>().FromSql(string.Format(@"select a.* FROM public.""PosTrxes"" a 
            //left join public.""PosTrxLineItems"" b on a.""Id""  = b.""PosTrxId"" 
            //left join public.""PosTrxMops"" c on a.""Id""  = c.""PosTrxId"" 
            //left join public.""PosMops"" d on c.""PosMopId""  = d.""Id"" 
            //where b.""FuelItemTag""  is null
            //and b.""Id"" = '1aa78939-7aa7-42b3-92fc-e2f8e934ddbd'
            //and a.""CreatedDateTime""  >=  '{0}' ", "2023-03-01")).Include(a => a.PosTrxLineItems)
            //.Include(a => a.PosTrxMops)
            //.ThenInclude(a => a.PosMop).ToList();
            //var query = _unitOfWork.GetRepository<PosTrxes>().GetAll().Include(a => a.PosTrxLineItems)
            //    .Include.ToList();
            //Guid guid_ = new Guid("000147d3-dd35-4c8a-a354-42be800ca57d");
            var query = _unitOfWork.GetRepository<PosTrxes>().GetAll().Include(a => a.PosTrxLineItems)
.Include(a => a.PosTrxMops)
.ThenInclude(a => a.PosMop).Where(a => a.CreatedDateTime >= enddateTime && a.CreatedDateTime <= dateTime
&& a.PosTrxLineItems.Any(b => b.FuelItemTag == null) //&& a.Id == guid_
 ).ToList();

            //            var query = _unitOfWork.GetRepository<PosTrxes>().GetAll().Include(a => a.PosTrxLineItems)
            //.Include(a => a.PosTrxMops)
            //.ThenInclude(a => a.PosMop).Where(a => a.PosTrxLineItems.Any(b => b.FuelItemTag == null) && a.Id == guid_
            //).ToList();

            foreach (var item in query)
            {
                var posTrxLineItems = item.PosTrxLineItems;
                var Mop = item.PosTrxMops?.FirstOrDefault()?.PosMop;
                var PosTrxMops = item.PosTrxMops;
                var fuelItemsFromRealPump = posTrxLineItems.Where(i => !string.IsNullOrEmpty(i.FuelItemFdcTransactionSeqNo) &&
                                                          i.FuelItemSoldOnPumpNozzleId != null);
                if (Mop == null)
                    continue;

                //string mopjson = SerializeObject(Mop);
                //MS.WebCore.Logger.Logger.WriteLog("Mop：" + JsonConvert.SerializeObject(mopjson));
                if (fuelItemsFromRealPump.Any())
                {
                    MyTransaction SequenceNo;
                    foreach (var trxitem in fuelItemsFromRealPump)
                    {
                        if (!string.IsNullOrEmpty(trxitem.FuelItemTag) || trxitem.FuelItemFdcTransactionSeqNo == null)
                            continue;
                        MS.WebCore.Logger.Logger.WriteLog("FuelItemFdcTransactionSeqNo：" + trxitem.FuelItemFdcTransactionSeqNo);
                        SequenceNo = findCardInfoByBusinessUnitInfoAndSequenceNo(item.TargetBusinessUnitId.ToString(), trxitem.FuelItemFdcTransactionSeqNo, trxitem.FuelItemSoldOnPumpNozzleId.ToString(), item.CreatedDateTime, Mop.PaymentId == 4);
                        if (SequenceNo != null)
                        {
                            MS.WebCore.Logger.Logger.WriteLog("FuelItemFdcTransactionSeqNo：" + trxitem.FuelItemFdcTransactionSeqNo + "card_no：" + SequenceNo.card_no);
                            var carno = SequenceNo.card_no;
                            if (carno.Length <= 8)//感应卡
                            {
                                if (SequenceNo.card_type != 1)
                                    continue;
                            }
                            else //CPU卡
                            {
                                if (SequenceNo.card_type != 4)
                                    continue;
                            }

                            var AspNetUsers = _AuthContext.GetRepository<AspNetUsers>().GetAll()
                            .Include(a => a.UserSubIdentities)
                            .Where(a => a.UserSubIdentities.Any(b => b.Identity == SequenceNo.card_no && b.Type == FuelItemTagDto.SmartFuelIcCardSystemName)).FirstOrDefault();
                            string AspNetUsersjson = SerializeObject(AspNetUsers);
                            MS.WebCore.Logger.Logger.WriteLog("FuelItemFdcTransactionSeqNo：" + trxitem.FuelItemFdcTransactionSeqNo + "AspNetUsers: " + AspNetUsersjson);
                            var tagInfo = new FuelItemTagDto()
                            {
                                TagLinkedServiceIdentityUser = new UserInfos
                                {
                                    Id = Guid.Parse(AspNetUsers.Id),
                                    UserName = AspNetUsers.UserName,
                                    Alias = BuidUploadOrNot(item.TargetBusinessUnitId.ToString()) ? "" : AspNetUsers.Alias,
                                    RestrictedInBusinessUnits = { }
                                },
                                TagSystemName = FuelItemTagDto.SmartFuelIcCardSystemName,
                                TagId = SequenceNo.card_no,
                                TagType = FuelItemTagDto.SmartFuelIcCardTagName,
                                Detail = "This Fuel Item from real pump is authorized by an attandant's smartFuel IC card"
                            };
                            trxitem.FuelItemTag = JsonConvert.SerializeObject(tagInfo);
                            _unitOfWork.GetRepository<PosTrxLineItems>().Update(trxitem);
                            await _unitOfWork.SaveChangesAsync();//提交
                            MS.WebCore.Logger.Logger.WriteLog("FuelItemFdcTransactionSeqNo：" + trxitem.FuelItemFdcTransactionSeqNo + "FuelItemTag：" + trxitem.Id.ToString());
                        }
                        else if (Mop.PaymentId == 4)
                        {
                            var entity = _unitOfWork.GetRepository<NozzleAssignments>().GetAll()
                                .Where(a => a.NozzleId == trxitem.FuelItemSoldOnPumpNozzleId && a.TargetBusinessUnitId == item.TargetBusinessUnitId)
                                .FirstOrDefault();
                            if (entity != null)
                            {
                                var AspNetUsersV2 = _AuthContext.GetRepository<AspNetUsers>().GetAll()
                                .Include(a => a.UserSubIdentities)
                                .Include(a => a.IdentityUserBusiUnitM2m)
                                .Where(a => a.IdentityUserBusiUnitM2m
                                .Any(b => b.BusinessUnitId == item.TargetBusinessUnitId)
                                && a.UserName == entity.OperatorName)
                                .FirstOrDefault();
                                if (AspNetUsersV2 != null)
                                {
                                    var tagInfo = new FuelItemTagDto()
                                    {
                                        TagLinkedServiceIdentityUser = new UserInfos
                                        {
                                            Id = Guid.Parse(AspNetUsersV2.Id),
                                            UserName = AspNetUsersV2.UserName,
                                            Alias = BuidUploadOrNot(item.TargetBusinessUnitId.ToString()) ? "" : AspNetUsersV2.Alias
                                        },
                                        TagSystemName = FuelItemTagDto.SmartFuelIcCardSystemName,
                                        TagId = AspNetUsersV2.UserSubIdentities?.FirstOrDefault().Identity,
                                        TagType = FuelItemTagDto.SmartFuelIcCardTagName,
                                        Detail = "This Fuel Item from real pump is authorized by IC card"
                                    };
                                    trxitem.FuelItemTag = JsonConvert.SerializeObject(tagInfo);
                                    _unitOfWork.GetRepository<PosTrxLineItems>().Update(trxitem);
                                    await _unitOfWork.SaveChangesAsync();//提交
                                    MS.WebCore.Logger.Logger.WriteLog("FuelItemTag：" + trxitem.Id.ToString());
                                }
                            }
                        }
                    }

                }
            }
            return null;
        }
        public bool BuidUploadOrNot(string buid)
        {

            bool __ = buid == "db3b74ff-412c-45fb-9887-9b10aa179704"
                         || buid == "f8c634fd-a231-456f-bd36-c6ee856820bc"
                         || buid == "df7033c4-ea67-48e3-ac4d-344ce22c6dda"
                         || buid == "9e0f39d7-3e63-4448-9347-e5f6ea0b1c13"
                         || buid == "fad023b9-333e-4a77-bea9-b07c95e5cad3"
                         || buid == "0c999874-3f3e-434c-8ee7-cd57bc34c33d"
                         || buid == "3d2122d2-fb89-415a-8310-4d5646804cc0";
            return __;
        }
        public MyTransaction findCardInfoByBusinessUnitInfoAndSequenceNo(string businessUnitId, string trxSequenceNo, string nozzleNo, DateTime dateTime, bool operatorIcCard)
        {
            DateTime requestDateTimeStart = dateTime.AddMilliseconds(-2 * 24 * 60 * 60 * 1000);
            DateTime requestDateTimeEnd = dateTime.AddMilliseconds(3 * 24 * 60 * 60 * 1000);

            string requestDateTimeStartString = requestDateTimeStart.ToString("yyyy-MM-dd HH:mm:ss");
            string requestDateTimeEndString = requestDateTimeEnd.ToString("yyyy-MM-dd HH:mm:ss");
            string car = operatorIcCard ? " trx.oper_card_no = ci.card_no" : "trx.card_info_id = ci.id";
            var sql = string.Format(@"
     SELECT trx.trx_sequence_no, trx.transaction_time, ci.card_no, ci.card_type, ci.card_class, ci.holder,
            ai.offline_account_id, ai.belong_to, trx.nozzle_no 
            FROM public.card_info ci 
            LEFT JOIN public.offline_transaction_info trx ON {5}
            LEFT JOIN public.account_info ai ON ai.id = ci.account_info_id 
            WHERE trx.business_unit_info_id = '{0}'
            AND trx.trx_sequence_no = '{1}'
            AND trx.nozzle_no = '{2}'
            AND trx.transaction_time > '{3}' 
            AND trx.transaction_time < '{4}'
            AND trx.transaction_type = 10 
            AND trx.amount <> 0 
            order by trx.transaction_time desc", businessUnitId, trxSequenceNo, nozzleNo, requestDateTimeStartString, requestDateTimeEndString, car);

            var results = _AccountingContext.DbContext.TransactionInfoDtos
                .FromSqlRaw(sql)
                  .FirstOrDefault();
            return results;
        }
        public MyTransaction findOperatorCardInfoByBusinessUnitInfoAndSequenceNo(string businessUnitId, string trxSequenceNo, string nozzleNo, DateTime dateTime)
        {
            DateTime requestDateTimeStart = dateTime.AddMilliseconds(-2 * 24 * 60 * 60 * 1000);
            DateTime requestDateTimeEnd = dateTime.AddMilliseconds(3 * 24 * 60 * 60 * 1000);

            string requestDateTimeStartString = requestDateTimeStart.ToString("yyyy-MM-dd HH:mm:ss");
            string requestDateTimeEndString = requestDateTimeEnd.ToString("yyyy-MM-dd HH:mm:ss");
            var sql = string.Format(@"
     SELECT trx.trx_sequence_no, trx.transaction_time, ci.card_no, ci.card_type, ci.card_class, ci.holder,
            ai.offline_account_id, ai.belong_to, trx.nozzle_no 
            FROM public.card_info ci 
            LEFT JOIN public.offline_transaction_info trx ON trx.oper_card_no = ci.card_no
            LEFT JOIN public.account_info ai ON ai.id = ci.account_info_id 
            WHERE trx.business_unit_info_id = '{0}'
            AND trx.trx_sequence_no = '{1}'
            AND trx.nozzle_no = '{2}'
            AND trx.transaction_time > '{3}' 
            AND trx.transaction_time < '{4}'
            AND trx.transaction_type = 10 
            AND trx.amount <> 0 
            order by trx.transaction_time desc", businessUnitId, trxSequenceNo, nozzleNo, requestDateTimeStartString, requestDateTimeEndString);

            var results = _AccountingContext.DbContext.TransactionInfoDtos
                .FromSqlRaw(sql)
                .FirstOrDefault();
            return results;
        }
        public string SerializeObject(object obj)
        {
            JsonSerializerSettings settings = new JsonSerializerSettings();
            settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;
            string mopjson = JsonConvert.SerializeObject(obj, settings);
            return mopjson;
        }
    }
}
