using Com.Bocom.OpenApi;
using Kivii;
using Kivii.Finances.Entities;
using Kivii.Linq;
using Kivii.Web;
using Njzj.Bocoms.Openapis.Entities;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Njzj.Bocoms.Openapis
{
    public class SettlementGenerateReceiveCode : RestfulExecution<Settlement>
    {
        public List<Guid> SettlementKvids { get; set; }
        public string View { get; set; }

        public string PayMerTranNo { get; set; }//唯一的业务编号,可以不传,系统将自动从Guid转化

        public override object OnExecution(IRequest req, IResponse res)
        {
            SettlementKvids.ThrowIfNullOrEmpty("请传入要收款的结算!");
            var conn = KiviiContext.GetOpenedDbConnection<Settlement>();
            var settlements = conn.SelectByIds<Settlement>(SettlementKvids);
            settlements.ThrowIfNullOrEmpty("未找到要收款的结算信息");
            var rtns = new RestfulExecutionResponse<MPNG020702ResponseV1>();
            rtns.Results = new List<MPNG020702ResponseV1>();
            try
            {
                var results = Extension.GenerateReceiveCode(settlements, PayMerTranNo);
                var payMerTranNo = results.rsp_body.pay_mer_tran_no;

                var order = Extension.GetReceiveCodeOrder(payMerTranNo);
                order.pay_mer_tran_no = payMerTranNo;
                order.display_code_text = results.rsp_body.display_code_text;

                var connB = KiviiContext.GetOpenedDbConnection<ReceiveCode>();
                var codeKvid = Guid.NewGuid();
                var code = new ReceiveCode();
                code.Kvid = codeKvid;
                code.trans_code = results.rsp_head.trans_code;
                code.response_code = results.rsp_head.response_code;
                code.response_status = results.rsp_head.response_status;
                code.response_time = results.rsp_head.response_time;
                code.response_msg = results.rsp_head.response_msg;
                code.shop_id = results.rsp_body.shop_id;
                code.pay_mer_tran_no = payMerTranNo;
                code.display_code_text = results.rsp_body.display_code_text;

                code.tran_state = order.rsp_body.tran_state;
                code.tran_state_code = order.rsp_body.tran_state_code;
                code.tran_state_msg = order.rsp_body.tran_state_msg;
                code.mer_memo = order.rsp_body.mer_memo;
                code.total_amount = order.rsp_body.total_amount;
                code.order_status = order.rsp_body.order_status;
                code.tran_content = order.rsp_body.tran_content;

                List<ReceiveCodeDetail> codeDetails = new List<ReceiveCodeDetail>();
                foreach (var item in settlements)
                {
                    var detail = new ReceiveCodeDetail();
                    detail.PayMerTranNo = payMerTranNo;
                    detail.ReceiveCodeKvid = code.Kvid;
                    detail.PayerName = item.PayerName;
                    detail.BizId = item.BizId;
                    detail.BizType = item.BizType;
                    detail.BizKvid = item.Kvid;
                    codeDetails.Add(detail);
                }
                var trans = connB.OpenTransaction();
                try
                {
                    foreach (var item in codeDetails)
                    {
                        connB.Insert(item);
                    }
                    connB.Insert(code);
                    trans.Commit();
                }
                catch (Exception ex)
                {
                    trans.Rollback();
                    throw ex;
                }

                if (View.IsNullOrEmpty())
                {
                    rtns.Results.Add(order);
                    return rtns;
                }
                else
                {
                    return new HttpResult
                    {
                        Response = order,
                        View = View
                    };
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
    }

    public class ReceiveCodeCheckState : RestfulExecution<ReceiveCode>
    {
        public string PayMerTranNo { get; set; }

        public override object OnExecution(IRequest req, IResponse res)
        {
            PayMerTranNo.ThrowIfNullOrEmpty("请传入订单号!");

            var conn = KiviiContext.GetOpenedDbConnection<ReceiveCode>();
            var existCode = conn.Single<ReceiveCode>(o => o.pay_mer_tran_no == PayMerTranNo);
            if (existCode == null) throw new Exception("未找到此扫码订单");
            var rtns = new RestfulExecutionResponse<ReceiveCode>();
            rtns.Results = new List<ReceiveCode>();

            if (existCode.tran_state != "PROCESS")
            {
                rtns.Results.Add(existCode);
                return rtns;
            }

            var order = Extension.GetReceiveCodeOrder(PayMerTranNo);
            if (order.rsp_body.tran_state != existCode.tran_state)
            {
                existCode.tran_state = order.rsp_body.tran_state;
                existCode.AddOnlyProperties(o => o.tran_state);
                existCode.tran_state_code = order.rsp_body.tran_state_code;
                existCode.AddOnlyProperties(o => o.tran_state_code);
                existCode.tran_state_msg = order.rsp_body.tran_state_msg;
                existCode.AddOnlyProperties(o => o.tran_state_msg);
                existCode.mer_memo = order.rsp_body.mer_memo;
                existCode.AddOnlyProperties(o => o.mer_memo);
                existCode.total_amount = order.rsp_body.total_amount;
                existCode.AddOnlyProperties(o => o.total_amount);
                existCode.order_status = order.rsp_body.order_status;
                existCode.AddOnlyProperties(o => o.order_status);
                existCode.tran_content = order.rsp_body.tran_content;
                existCode.AddOnlyProperties(o => o.tran_content);
                conn.UpdateOnly(existCode);
                existCode.RemoveAllOnlyProperties();
            }
            rtns.Results.Add(existCode);

            return rtns;
        }
    }
}
