using Com.Bocom.OpenApi.Utils;
using Kivii;
using Kivii.Finances.Entities;
using Kivii.Finances;
using Kivii.Finances.Transforms;
using Kivii.Linq;
using Kivii.Text;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static Com.Bocom.OpenApi.AddContractOrderRequestV2.AddContractOrderRequestV2Biz;
using static System.Net.Mime.MediaTypeNames;
using System.Reflection;
using System.Web.Caching;

namespace Com.Bocom.OpenApi
{
    public static class Extension
    {
        public static AddContractOrderResponseV2 RequestAddContractOrderV2(Settlement settlement, out string err)
        {
            if (settlement == null)
            {
                err = string.Empty;
                return null;
            }
            DefaultBocomClient client = new DefaultBocomClient(Configs.APP_ID, Configs.MY_PRIVATE_KEY, Configs.APIGW_PUBLIC_KEY, BocomConstants.ENCRYPT_TYPE_RSA_AND_AES);
            /**
			* 测试环境可以忽略SSL证书告警，生产环境不可忽略
			*/
            client.IgnoreSslHostnameVerifier();

            var bizKvid = settlement.Kvid.ToString();
            var bizId = settlement.BizId;
            var request = new AddContractOrderRequestV2();
            request.SetServiceUrl(Configs.APIGW_URL_ADDRESS + Configs.AddContractOrderRequestV2);

            var bizContent = new AddContractOrderRequestV2.AddContractOrderRequestV2Biz();
            bizContent.org_id = Configs.ORG_ID;
            bizContent.bat_id = bizId;
            bizContent.cont_order_list = new List<ContOrder>();
            var contorder = new ContOrder();
            contorder.cont_id = bizKvid;
            contorder.org_id = bizContent.org_id;
            contorder.ori_payer = settlement.PayerName;
            //contorder.ori_ac = "";
            //contorder.ori_addr = "仅记录";
            //contorder.ori_tel_no = "仅记录";
            //contorder.ori_other_info1 = "仅记录";
            //contorder.ori_other_info2 = "仅记录";
            //contorder.ori_other_info3 = "仅记录";
            contorder.ori_itm_nme = settlement.BizId;
            contorder.ori_amt = settlement.AmountPlan.ToString();
            contorder.ori_offset_amt = (settlement.AmountPlan - settlement.Amount).ToString();
            contorder.ori_act_amt = settlement.Amount.ToString();
            //contorder.attach_code = "";
            contorder.remark = settlement.Remark;
            //contorder.offset_remark = "测试2";
            contorder.payment_period = $"{DateTime.Now.AddMonths(-2).ToString("yyyy-MM-dd")}~{DateTime.Now.AddMonths(7).ToString("yyyy-MM-dd")}";
            contorder.agreement_type = "-1";
            bizContent.cont_order_list.Add(contorder);

            request.SetBizContent(bizContent);
            var response = client.Execute(request, Guid.NewGuid().ToString().Replace("-", ""));
            var rtns = new AddContractOrderResponseV2();
            if (response.IsSuccess())
            {
                rtns = response as AddContractOrderResponseV2;
                err = string.Empty;
                return rtns;
            }
            else
            {
                err = response.GetRspMsg();
                return null;
            }

        }

        public static DelContractOrderResponseV1 RequestDelContractOrderResponseV1(Settlement settlement, out string err)
        {
            if (settlement == null || settlement.Metadata.IsNullOrEmpty() || !settlement.Metadata.ContainsKey("BocomBillId"))
            {
                err = string.Empty;
                return null;
            }
            var billId = settlement.Metadata["BocomBillId"];
            //Console.WriteLine($"---------------BocomBillId:{billId}-------------------");
            DefaultBocomClient client = new DefaultBocomClient(Configs.APP_ID, Configs.MY_PRIVATE_KEY, Configs.APIGW_PUBLIC_KEY, BocomConstants.ENCRYPT_TYPE_RSA_AND_AES);
            /**
			* 测试环境可以忽略SSL证书告警，生产环境不可忽略
			*/
            client.IgnoreSslHostnameVerifier();
            var request = new DelContractOrderRequestV1();
            request.SetServiceUrl(Configs.APIGW_URL_ADDRESS + Configs.DelContractOrderRequestV1);

            var bizContent = new DelContractOrderRequestV1.DelContractOrderRequestV1Biz();
            bizContent.org_id = Configs.ORG_ID;
            bizContent.bill_id = billId;
            request.SetBizContent(bizContent);
            var response = client.Execute(request, Guid.NewGuid().ToString().Replace("-", ""));
            var rtns = new DelContractOrderResponseV1();
            if (response.IsSuccess())
            {
                rtns = response as DelContractOrderResponseV1;
                err = string.Empty;
                //Console.WriteLine($"---------------DelContractOrder:Success-------------------");
                return rtns;
            }
            else
            {
                err = response.GetRspMsg();
                //Console.WriteLine($"---------------err:{err}-------------------");
                return null;
            }
        }

        /// <summary>
        /// 智慧记账自动核销结算
        /// </summary>
        /// <param name="payments"></param>
        /// <param name="settlement"></param>
        /// <param name="payingMethod"></param>
        /// <param name="conn"></param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static bool AutoPay(List<Payment> payments, Settlement settlement, List<PayingMethod> payingMethods, IDbConnection conn = null)
        {
            payments.ThrowIfNullOrEmpty("请传入付款信息!");
            settlement.ThrowIfNull("请传入结算信息!");
            if (payments.Exists(o => o.Type != PaymentType.Split)) throw new Exception("付款类型不支持!");
            bool useTransaction = conn == null;//是否启用事务，如果外部未传入conn,启用内部事务
            if (conn == null)
            {
                conn = KiviiContext.GetOpenedDbConnection<Payment>();
            }
            var accountBiz = settlement.Currency.GetBizAccount();


            var dynamicSplitPayments = new List<Payment>();
            var allPays = new List<Pay>();
            var allAccountDetails = new List<AccountDetail>();

            foreach (var payingMethod in payingMethods)
            {
                var amount = payingMethod.Amount;
                var payment = payments.FirstOrDefault(o => o.Kvid == payingMethod.Kvid);
                (payment == null).ThrowIfTrue("未找到付款数据!");
                if (payment.Amount - payment.AmountUsed < amount) amount = payment.Amount - payment.AmountUsed;
                (payingMethod.Amount > 0 && payingMethod.Amount > payment.Amount - payment.AmountUsed).ThrowIfTrue($"所选付款方式余额不足,可用余额:{payment.Amount - payment.AmountUsed}");
                if (payingMethod.Amount > 0 && payingMethod.Amount < amount) amount = payingMethod.Amount;//外部指定分摊多少钱就按照指定的费用进行分摊 否则就按照能使用的最大金额进行分摊
                var settlements = new List<Settlement>();
                settlements.Add(settlement);
                var dynamicPayPayment = settlements.Paying(payment, accountBiz, out var pays, out var accountDetail, amount, payingMethod.Remark);
                allPays.AddRange(pays);
                dynamicSplitPayments.Add(dynamicPayPayment);
                allAccountDetails.Add(accountDetail);
            }

            IDbTransaction trans = null;//事务，如果外部来了Connection，不生成事务
            if (useTransaction) trans = conn.OpenTransaction();
            try
            {
                foreach (var item in allPays)
                {
                    conn.Insert(item);
                }
                foreach (var item in dynamicSplitPayments)
                {
                    item.SerialNumber = item.GetSubSerialNumber(conn);
                    conn.Insert(item);//创建DynamicSplitPayment
                }
                allAccountDetails.ForEach(o => o.Insert(conn));//创建账户明细
                foreach (var item in payments)
                {
                    item.RecalculateAmountUsed(conn);
                    if (item.Type == PaymentType.Split) item.RecalculateAssignAmount(conn);
                }
                if (!settlement.OnlyProperties.IsNullOrEmpty()) conn.UpdateOnly(settlement);//更新了Paykvid和AmountPayment

                trans?.Commit();

                return true;
            }
            catch (Exception ex)
            {
                trans?.Rollback();
                throw ex;
            }
        }


        public static MPNG210001ResponseV1 GenerateReceiveCode(List<Settlement> settlements)
        {
            if (settlements.IsNullOrEmpty()) return null;
            if (settlements.Exists(o => o.OffsetKvid != Guid.Empty || o.AmountPayment > 0)) throw new Exception("存在不符合生成收款码条件的结算");
            var amount = settlements.Sum(o => o.Amount);
            if (amount <= 0) return null;
            var uniqueCode = Guid.NewGuid().ToString();//生成二维码的唯一性交易编号
            var bizIds = settlements.ConvertAll(o => o.BizId).Join("、");
            var remark = settlements.ConvertAll(o => o.BizId).Join("、");

            if (bizIds.Length > 200) bizIds = bizIds.Substring(0, 200);//根据对接要求长度限制长度
            if (remark.Length > 500) remark = remark.Substring(0, 500);//根据对接要求长度限制长度

            var rtnTests = new MPNG210001ResponseV1();
            rtnTests.rsp_body = new MPNG210001ResponseV1.RspBody();
            rtnTests.SetBizState("S");
            rtnTests.SetRspCode("1");
            rtnTests.SetRspMsg("1");
            rtnTests.rsp_body.display_code_text = "http://yunbanktest.bankcomm.com/tcipp/pmss/cipp.jsp?qrCode=https://qr.95516.com/03010000/kl6im4od20200804123754";
            rtnTests.rsp_body.pay_mer_tran_no = uniqueCode;

            return rtnTests;



            DefaultBocomClient client = new DefaultBocomClient(Configs.QR_CODE_APP_ID, Configs.QR_CODE_MY_PRIVATE_KEY, Configs.QR_CODE_APIGW_PUBLIC_KEY, BocomConstants.ENCRYPT_TYPE_RSA_AND_AES);
            /**
   * 测试环境可以忽略SSL证书告警，生产环境不可忽略
   */
            client.IgnoreSslHostnameVerifier();

            var request = new MPNG210001RequestV1();
            request.SetServiceUrl(Configs.QR_CODE_APIGW_URL_ADDRESS + Configs.MPNG210001RequestV1);
            var bizContent = new MPNG210001RequestV1.MPNG210001RequestV1Biz();
            bizContent.req_head = new MPNG210001RequestV1.MPNG210001RequestV1Biz.ReqHead();
            bizContent.req_head.trans_time = DateTime.Now.ToString("yyyyMMddHHmmss");
            bizContent.req_head.version = "V-1.0";
            bizContent.req_body = new MPNG210001RequestV1.MPNG210001RequestV1Biz.ReqBody();
            bizContent.req_body.tran_scene = "B2C-API-DISPLAYCODE";
            bizContent.req_body.mer_ptc_id = Configs.mer_ptc_id;//"301310063009501";//商户号,需要配置信息到位
            bizContent.req_body.mer_trade_time = DateTime.Now.ToString("HHmmss");
            bizContent.req_body.mer_trade_date = DateTime.Now.ToString("yyyyMMdd");
            bizContent.req_body.pay_mer_tran_no = uniqueCode;
            bizContent.req_body.total_amount = amount.ToString();
            bizContent.req_body.location = "ONLINE";
            bizContent.req_body.currency = "CNY";
            bizContent.req_body.tran_content = bizIds;
            bizContent.req_body.mer_memo = remark;
            request.SetBizContent(bizContent);
            var response = client.Execute(request, uniqueCode.Replace("-", ""));

            if (response.IsSuccess())
            {
                //-----------------------记录下这份收款码的数据的信息,如果这份订单取消了就要作废--------------------------------
                var rtns = response as MPNG210001ResponseV1;
                return rtns;
            }
            else
            {
                throw new Exception($"ReturnCode:{response.GetRspCode()}{Environment.NewLine}ReturnMsg:{response.GetRspMsg()}");
            }
        }

        public static MPNG020702ResponseV1 GetReceiveCodeOrder(string payMerTranNo,List<Settlement> settlements)
        {
            payMerTranNo.ThrowIfNullOrEmpty("缺少订单号信息");
            if (settlements.IsNullOrEmpty()) return null;
            if (settlements.Exists(o => o.OffsetKvid != Guid.Empty || o.AmountPayment > 0)) throw new Exception("存在不符合生成收款码条件的结算");
            var amount = settlements.Sum(o => o.Amount);
            if (amount <= 0) return null;
            var uniqueCode = Guid.NewGuid().ToString();//生成二维码的唯一性交易编号
            var bizIds = settlements.ConvertAll(o => o.BizId).Join("、");
            var remark = settlements.ConvertAll(o => o.BizId).Join("、");

            if (bizIds.Length > 200) bizIds = bizIds.Substring(0, 200);//根据对接要求长度限制长度
            if (remark.Length > 500) remark = remark.Substring(0, 500);//根据对接要求长度限制长度

            var rtnTests = new MPNG020702ResponseV1();
            rtnTests.SetBizState("S");
            rtnTests.SetRspCode("1");
            rtnTests.SetRspMsg("1");
            rtnTests.rsp_body = new MPNG020702ResponseV1.RspBody();
            rtnTests.rsp_body.mer_memo = remark;
            rtnTests.rsp_body.total_amount = amount.ToString();
            rtnTests.rsp_body.tran_content = bizIds;
            return rtnTests;


            DefaultBocomClient client = new DefaultBocomClient(Configs.QR_CODE_APP_ID, Configs.QR_CODE_MY_PRIVATE_KEY, Configs.QR_CODE_APIGW_PUBLIC_KEY, BocomConstants.ENCRYPT_TYPE_RSA_AND_AES);
            /**
            * 测试环境可以忽略SSL证书告警，生产环境不可忽略
            */
            client.IgnoreSslHostnameVerifier();

            var request = new MPNG020702RequestV1();
            request.SetServiceUrl(Configs.QR_CODE_APIGW_URL_ADDRESS + Configs.MPNG020702RequestV1);
            var bizContent = new MPNG020702RequestV1.MPNG020702RequestV1Biz();
            bizContent.req_head = new MPNG020702RequestV1.MPNG020702RequestV1Biz.ReqHead();
            bizContent.req_head.trans_time = DateTime.Now.ToString("yyyyMMddHHmmss");
            bizContent.req_head.version = "1.0";
            bizContent.req_body = new MPNG020702RequestV1.MPNG020702RequestV1Biz.ReqBody();
            bizContent.req_body.tran_scene = "B2C-API-DISPLAYCODE";
            bizContent.req_body.mer_ptc_id = Configs.mer_ptc_id;//"301310063009501";//商户号,需要配置信息到位
            bizContent.req_body.mer_trade_date = DateTime.Now.ToString("yyyyMMdd");
            bizContent.req_body.pay_mer_tran_no = payMerTranNo;// Guid.NewGuid().ToString();

            bizContent.req_body.require_fields = new List<MPNG020702RequestV1.MPNG020702RequestV1Biz.ReqBody.RequireFields>();
            var require_field = new MPNG020702RequestV1.MPNG020702RequestV1Biz.ReqBody.RequireFields();
            require_field.require_field = "bank_tran_no,third_party,third_party_tran_no,payment_info,refund_info";
            bizContent.req_body.require_fields.Add(require_field);

            request.SetBizContent(bizContent);
            var response = client.Execute(request, Guid.NewGuid().ToString().Replace("-", ""));

            if (response.IsSuccess())
            {
                var rtns = response as MPNG020702ResponseV1;
                return rtns;
            }
            else
            {
                throw new Exception($"ReturnCode:{response.GetRspCode()}{Environment.NewLine}ReturnMsg:{response.GetRspMsg()}");
            }
        }
    }
}
