using Bp.Sync.BackEnd.Infrastructure.Repositories.FcBusinesses;
using Bp.Sync.Domain.Elastics.FcBusinesses.Products;
using Bp.Sync.Dto.Results;
using CommonLibrary;
using Dapper;
using EasyNetQ;
using Microsoft.Extensions.Configuration;
using System;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace Bp.Sync.BackEnd.Application.Commands.FcBusinesses.ProductOutbounds
{
    public class SyncFcProductOutboundHandler : MediatR.IRequestHandler<SyncFcProductOutboundCommand, BaseResult>
    {
        private readonly IDbConnection _dbConnection;
        private readonly IFcProductOutboundRepository _FcProductOutboundRepository;
        private readonly IBus _bus;

        public SyncFcProductOutboundHandler(IConfiguration configuration, IFcProductOutboundRepository FcProductOutboundRepository, IBus bus)
        {
            var connectionString = configuration.GetConnectionString("FcBusinessConnection");
            _dbConnection = new SqlConnection(connectionString);
            _FcProductOutboundRepository = FcProductOutboundRepository;
            _bus = bus;
        }

        public async Task<BaseResult> Handle(SyncFcProductOutboundCommand request, CancellationToken cancellationToken)
        {
            var rs = new BaseResult();

            if (request.Ids.Count() > 10000)
            {
                var length = request.Ids.Count();
                if (length > 0)
                {
                    for (int i = 0; i <= length / 1000; i++)
                    {
                        if (length > i * 10000)
                        {
                            var ids = request.Ids.Skip(i * 10000).Take(10000).ToList();
                            if (ids.Count() > 0)
                            {
                                await _bus.SendAsync($"SyncToElasticFcProductOutbound", ids.ConvertListLongToString());
                            }
                        }
                    }
                }
                return new BaseResult { Result = Result.Success, Message = $"sent {length} FcProductOutbounds" };
            }
            if (!request.Ids.Any())
            {
                rs.Message = $"no data to update";
                rs.Result = Result.Success;
                return rs;
            }

            try
            {
                var p = new Dto.DapperTypes.IdsParam(request.Ids);
                var inbounds = await _dbConnection.QueryAsync<FcProductOutboundElastic>("Sync_ProductOutbound_Get_By_List_Id", p, commandType: CommandType.StoredProcedure);
                if (inbounds.Any())
                {
                    //lay ra danh sach inbound bill
                    var billids = inbounds.Select(x => x.BillId).Distinct().ToList();
                    var p2 = new Dto.DapperTypes.IdsParam(billids);
                    var bills = await _dbConnection.QueryAsync<Domain.Entities.FcBusinesses.Bills.OutboundBill>("Sync_OutboundBill_Get_By_List_Id", p2, commandType: CommandType.StoredProcedure);

                    foreach (var item in inbounds)
                    {
                        var bill = bills.FirstOrDefault(x => x.Id == item.BillId);
                        item.BillIsDeleted = bill?.IsDeleted;
                        item.BillStatus = bill?.BillStatus;
                        item.BillType = bill?.BillType;
                        item.BillCreatedTime = bill?.CreatedTime;
                        item.BillCompletedDate = bill?.CompletedDate;
                        item.BillPartnerId = bill?.PartnerId;
                        item.BillOriginBranchId = bill?.OriginBranchId;
                        item.BillDestinationBranchId = bill?.DestinationBranchId;
                        if (item.BranchId == 0)
                            item.BranchId = bill.OriginBranchId;
                    }

                    var rs2 = await _FcProductOutboundRepository.AddManyAsync(inbounds);
                    if (rs2.Result == Result.Success)
                    {
                        await _dbConnection.ExecuteAsync("Synced_ProductOutbound_By_List_Id", p, commandType: CommandType.StoredProcedure);
                        rs.Message = $"{inbounds.Count()} synced";
                        rs.Result = Result.Success;
                    }
                    else
                    {
                        rs.Message = $"can not insert db";
                        rs.Result = Result.Success;
                    }
                }
                else
                {
                    rs.Message = $"no data to update";
                    rs.Result = Result.Success;
                }
            }
            catch (Exception ex)
            {
                rs.Message = ex.Message.ToString();
                rs.Result = Result.SystemError;
            }
            return rs;
        }
    }
}