using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XYY.Common.Standard;
using XYY.Core.Standard.ExcelHelper.MSExcelHelper;
using XYY.Data.Standard;
using XYY.Data.Standard.Finance;
using XYY.Model.Standard;
using XYY.Model.Standard.Finance;
using XYY.Service.Standard.Finance.RedisCache;

namespace XYY.Service.Standard.Finance
{
    public interface IFinance_Customer_RemittanceService
    {
        Task<PageResult<View_Finance_Customer_Remittance>> GetPageResult(QueryModel queryModel);
        Task RejectionRemittance(Finance_Customer_Remittance remittance);
        Task PassRemittance(Finance_Customer_Remittance remittance);
        Task SetRemittanceDate(Finance_Customer_Remittance remittance);
        Task Input(string url, string userName);
    }

    public class Finance_Customer_RemittanceService : IFinance_Customer_RemittanceService
    {
        IFinance_Customer_AccountRepository _accountRepository;
        IFinance_Customer_RemittanceRepository _remittanceRepository;
        IFinance_CustomerDeliveryBillRepository _billRepository;
        IUserCustomerRepository _userCustomerRepository;
        ILadingBillService _LadingBillService;
        public Finance_Customer_RemittanceService(IFinance_Customer_RemittanceRepository remittanceRepository,
            IFinance_Customer_AccountRepository accountRepository,
            IFinance_CustomerDeliveryBillRepository billRepository,
             IUserCustomerRepository userCustomerRepository,
            ILadingBillService LadingBillService)
        {
            _remittanceRepository = remittanceRepository;
            _accountRepository = accountRepository;
            _billRepository = billRepository;
            _userCustomerRepository = userCustomerRepository;
            _LadingBillService = LadingBillService;
        }

        public async Task<PageResult<View_Finance_Customer_Remittance>> GetPageResult(QueryModel queryModel)
        {
            return await _remittanceRepository.GetPageResult(queryModel);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="updateRemittance"></param>
        /// <param name="tMessage">记录返回值</param>
        /// <returns></returns>
        public async Task PassRemittance(Finance_Customer_Remittance updateRemittance)
        {
            var remittance = await _remittanceRepository.GetAsync(updateRemittance.Id);
            var customerAccount = (await _accountRepository.QueryAsync(x => x.CustomerId == remittance.CustomerId)).FirstOrDefault();
            if (customerAccount == null)
                throw new Exception("未找到相关客户的帐户");
            remittance.PassDate = DateTime.Now;
            //取待付款状态，确保执行顺序
            var billList = await _billRepository.QueryBySqlAsync("select * from Finance_CustomerDeliveryBill(nolock) where customerId = @CustomerId and" +
                " Status=@Status and StartTime>='2021-10-01' order by StartTime ", new { CustomerId = updateRemittance.CustomerId, Status = FiannceServiceBillStatus.结算中 });

            if (billList.Any(x => x.StartTime <= updateRemittance.RemittanceDate && x.EndTime >= updateRemittance.RemittanceDate))
            {
                //更新相关帐单的本期收款金额
                billList.First(x => x.StartTime <= updateRemittance.RemittanceDate && x.EndTime >= updateRemittance.RemittanceDate).CurrentPeriod += updateRemittance.PaymentCNY;
            }


            foreach (var bill in billList)
            {
                //还款
                if (bill.AmountToBeRepaid <= remittance.PaymentCNY)
                {
                    bill.AmountToBeRepaid = 0;
                    bill.Repayment = bill.Arrears;
                    if (bill.LastRepaymentDate >= remittance.RemittanceDate)
                    {
                        //付款时间小于最后还款日,逾期天数归0
                        bill.CurrentOverdueDays = 0;
                    }
                    else
                    {
                        //计算逾期天数
                        if (bill.LastRepaymentDate.HasValue)
                            bill.CurrentOverdueDays = (int)(remittance.RemittanceDate - bill.LastRepaymentDate).Value.TotalDays;
                    }
                }
                else
                {
                    //部分还款
                    bill.AmountToBeRepaid -= remittance.PaymentCNY;
                    bill.Repayment += remittance.PaymentCNY;
                }
            }
            decimal PaymentCNY = remittance.PaymentCNY;
            string curreny = "CNY";
            decimal payc = PaymentCNY;
            if (remittance.Curreny != "CNY" && remittance.Curreny == customerAccount.Currency)
            {
                PaymentCNY = remittance.Payment;
                curreny = remittance.Curreny;
                payc = remittance.Payment;
            }
            FiannceServiceBillStatus preBillStatus = FiannceServiceBillStatus.结算中;
            foreach (var bill in billList)
            {
                //应对空帐单无应付金额，上一期帐单是什么值，空帐单就什么值
                if (bill.Receivables == 0) { bill.Status = preBillStatus; continue; }
                //还款欠款帐单
                decimal billReceivables = bill.Receivables - bill.Payment;
                if (PaymentCNY >= billReceivables)
                {
                    //如果充值金额大于该帐单应收款，更新帐单至已结算
                    PaymentCNY -= billReceivables;
                    bill.Payment += billReceivables;
                    bill.Status = FiannceServiceBillStatus.已还清;
                    preBillStatus = FiannceServiceBillStatus.已还清;
                }
                else if (PaymentCNY == 0)
                {
                    //如果充值金额无可用直接退出循环
                    break;
                }
                else
                {
                    //部分还款
                    bill.Payment += PaymentCNY;
                    PaymentCNY = 0;
                    preBillStatus = FiannceServiceBillStatus.结算中;
                }
                //更新帐单信息 
            }
            foreach (var bill in billList)
            {
                await _billRepository.UpdateAsync(bill);
            }
            //更新最大逾期天数            
            int maxCurrentOverdueDays = 0;
            if (billList.Where(x => x.Status == FiannceServiceBillStatus.结算中).Count() > 0)
                maxCurrentOverdueDays = billList.Where(x => x.Status == FiannceServiceBillStatus.结算中)
                    .Max(x => x.CurrentOverdueDays);
            else
                maxCurrentOverdueDays = 0;

            //增加头程账单处理逻辑
            await _LadingBillService.PassRemittanceForFirstBill(updateRemittance.CustomerId, billList.Where(x => x.BillTypeValue == (int)BillTypeEnum.头程帐单));
            //更新当前充值状态为成功 
            remittance.Status = CustomerRemittanceStatus.付款成功;
            remittance.PassDate = DateTime.Now;
            await _remittanceRepository.UpdateAsync(remittance);
            string message = ChargesService.Payment(new PaymentRequest
            {
                ChargeName = "线下付款",
                Currency = curreny,
                SettlementCurrency = curreny,
                CurrentOverdueDays = maxCurrentOverdueDays,
                AmountinOriginalCurrency = (double)remittance.Payment,
                CustomerId = remittance.CustomerId,
                Fee = (double)payc,
                BillId = remittance.Id.ToString(),
                SettlementRate = (double)remittance.Rate,
                FeeDescription = remittance.Remark,
                TransactionTime = remittance.RemittanceDate
            });
            if (message != "成功")
                throw new Exception(message);
        }

        public int CustomerId
        {
            get; set;
        }


        public string UserName
        {
            get; set;
        }

        public DateTime RemittanceDate
        {
            get; set;
        }

        public string Bank
        {
            get; set;
        }

        public string Curreny
        {
            get; set;
        }

        public string AccountNumber
        {
            get; set;
        }

        public decimal Payment
        {
            get; set;
        }

        public decimal Rate
        {
            get; set;
        }

        public decimal PaymentCNY
        {
            get; set;
        }

        public DateTime? PassDate
        {
            get; set;
        }

        public CustomerRemittanceStatus Status
        {
            get; set;
        }

        public string ReasonsForRejection
        {
            get; set;
        }

        public string Appendix
        {
            get; set;
        }
        /// <summary>
        /// 付款失败
        /// </summary>
        /// <param name="updateRemittance"></param>
        /// <returns></returns>
        public async Task RejectionRemittance(Finance_Customer_Remittance updateRemittance)
        {
            var remittance = await _remittanceRepository.GetAsync(updateRemittance.Id);
            if (remittance == null)
                throw new Exception("未找到相关付款信息");
            remittance.ReasonsForRejection = updateRemittance.ReasonsForRejection;
            remittance.Status = CustomerRemittanceStatus.付款失败;
            await _remittanceRepository.UpdateAsync(remittance);
        }

        public async Task SetRemittanceDate(Finance_Customer_Remittance updateRemittance)
        {
            var remittance = await _remittanceRepository.GetAsync(updateRemittance.Id);
            if (remittance == null)
                throw new Exception("未找到相关付款信息");
            remittance.RemittanceDate = updateRemittance.RemittanceDate;
            await _remittanceRepository.UpdateAsync(remittance);
        }

        public async Task Input(string url, string userName)
        {
            System.Net.WebClient client = new System.Net.WebClient();
            var data = client.DownloadData(url);
            if (data.Length > 0)
            {
                MSExcelHelper excelHelper = new MSExcelHelper();
                var list = excelHelper.LoadDataByByte<Mapping, Finance_Customer_RemittanceDto>(data);
                //校验异常数据
                if (!CollectionFlowCheck(list, out Tuple<string, List<dynamic>> checkInfo)) { throw new Exception(checkInfo.Item1); }
                foreach (var x in list)
                {
                    string number = x.CustomerNumber;
                    //var customer =
                    //(await _userCustomerRepository.QueryAsync(y => y.CustomerNumber == number)).FirstOrDefault();
                    //if (customer == null)
                    //{
                    //    throw new Exception("未找到客户编码" + x.AccountNumber);
                    //}
                    //else
                    //{
                    //    x.CustomerId = customer.Id;
                    //}
                    x.CustomerId = checkInfo.Item2.Where(p => (string)p.CustomerNumber == number).FirstOrDefault().Id;
                    x.Bank = "";
                    x.AccountNumber = "";
                    x.Curreny = "";
                    x.Rate = 1;
                    x.Status = CustomerRemittanceStatus.支付中;
                    x.CreateTime = DateTime.Now;
                    x.UserName = "";
                    x.Id = (int)await _remittanceRepository.InsertAsync(x);
                    await PassRemittance(x);
                };
            }
        }

        public bool CollectionFlowCheck(List<Finance_Customer_RemittanceDto> input, out Tuple<string, List<dynamic>> checkInfo)
        {
            string tips = string.Empty; bool result = true;
            var CollectionFlowInfo = _remittanceRepository.GetCollectionFlowEndTime().Result;
            var query = from a in input
                        join b in CollectionFlowInfo on a.CustomerNumber equals b.CustomerNumber
                        where a.RemittanceDate <= b.EndTime
                        select a;
            List<string> CustomerNumbers = CollectionFlowInfo.Select(x => (string)x.CustomerNumber).ToList();
            var query2 = input.Where(x => !CustomerNumbers.Any(y => x.CustomerNumber.Equals(y, StringComparison.OrdinalIgnoreCase)));
            if ((query != null && query.Count() > 0) || (query2 != null && query2.Count() > 0))
            {
                foreach (var item in query)
                {
                    //tips +=$"{item.CustomerNumber}，日期时间小于或等于最新一期帐单，无法导入。\r\n";
                }
                foreach (var item in query2)
                {
                    tips += $"{item.CustomerNumber}，客户信息不存在，无法导入。\r\n";
                    result = false;
                }
            }
            checkInfo = new Tuple<string, List<dynamic>>(tips, CollectionFlowInfo.ToList());
            return result;
        }
        public class CollectionFlow
        {
            public string CustomerNumber { get; set; }
            public int Id { get; set; }
            public DateTime? EndTime { get; set; }
        }
        public class Finance_Customer_RemittanceDto : Finance_Customer_Remittance
        {
            public string CustomerNumber
            {
                get; set;
            }
        }


        public class Mapping : MSExcelClassMapping<Finance_Customer_RemittanceDto>
        {
            public Mapping()
            {
                Map(x => x.PaymentCNY).Name("金额");
                Map(x => x.RemittanceDate).Name("日期");
                Map(x => x.CustomerNumber).Name("客户");
            }
        }
    }



}
