package com.izouma.nineth.service;

import com.alibaba.fastjson.JSONObject;
import com.izouma.nineth.config.GeneralProperties;
import com.izouma.nineth.config.IkudotpayProperties;
import com.izouma.nineth.domain.*;
import com.izouma.nineth.dto.pay.UniformPayResult;
import com.izouma.nineth.enums.*;
import com.izouma.nineth.exception.BusinessException;
import com.izouma.nineth.repo.DivMoneyRepo;
import com.izouma.nineth.repo.OrderRepo;
import com.izouma.nineth.repo.TransferMoneyInfoRepo;
import com.izouma.nineth.service.pay.PayHelper;
import com.izouma.nineth.service.pay.UniformPayConstants;
import com.izouma.nineth.utils.IPUtils;
import com.izouma.nineth.utils.SnowflakeIdWorker;
import com.izouma.nineth.utils.ikudot.IkudotpayClient;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

@Service
@AllArgsConstructor
@Slf4j
public class IkudotpayService {

    private GeneralProperties generalProperties;

    private IkudotpayProperties ikudotpayProperties;

    private IkudotpayClient ikudotpayClient;


    private DivMoneyRepo divMoneyRepo;

    private OrderRepo orderRepo;

    private TransferMoneyInfoRepo transferMoneyInfoRepo;

    private UserFundAccountService userFunAccountService;

    private SnowflakeIdWorker snowflakeIdWorker;

    private PayHelper payHelper;

    /**
     * h5支付
     * @param paymentInfo
     * @return
     */
    public JSONObject h5pay(PaymentInfo paymentInfo){
        String wapUrl = payHelper.resolveHome(paymentInfo.getProjectId());
        String wapName = payHelper.resolveName(paymentInfo.getProjectId());
        String returnUrl = payHelper.resolveReturnUrl(paymentInfo);

        String orderTime = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now());
        String timeExpire = DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now().plusMinutes(3));
        Integer fee = paymentInfo.getPayAmt().multiply(new BigDecimal(100)).intValue();
        JSONObject params = new JSONObject();
        params.put("fee", fee);
        params.put("out_trade_no", paymentInfo.getOrderNo());
        params.put("body", paymentInfo.getGoodsTitle());
        params.put("client_ip", IPUtils.getIpAddr());
        params.put("notify_url", paymentInfo.getNotifyUrl());
//        params.put("payment", "ALIPAY" );//可选，不指定时由用户决定
        params.put("origin_fee", fee);
        params.put("time_start",orderTime );
        params.put("time_expire",timeExpire );
//        params.put("fee_type", "CNY" );//可选货币类型
//        params.put("limit_credit", "0" ); //1为限制，0或不传为不限制
//        params.put("goods_tag","" );
//        params.put("goods_details", "");
//        params.put("shop_id", "");
//        params.put("device_id", "");
//        params.put("operator_id", "");
//        params.put("attach", "");//附加信息

        //场景信息
        JSONObject senceInfo = new JSONObject();
        senceInfo.put("wap_url", wapUrl);
        senceInfo.put("wap_name", wapName);
        senceInfo.put("return_url", returnUrl);
        params.put("sence_info", senceInfo);

        JSONObject result = ikudotpayClient.postJson("/openapi/pay/kdh5pay", params);

        return result;
    }

    /**
     * 转账给分账用户
     * @param divMoneyId
     * @return
     */
    @Transactional
    public TransferMoneyInfo transferDivMoney(Long divMoneyId, String reason){
        DivMoney divMoney = divMoneyRepo.findById(divMoneyId).orElseThrow(new BusinessException("分账记录不存在"));
        if(divMoney.getUserId() == null){
            throw new BusinessException("分账的用户ID不存在");
        }

        Order order = orderRepo.findById(divMoney.getOrderId()).orElseThrow(new BusinessException("分账订单未找到"));
        if(order.getStatus() != OrderStatus.FINISH){
            throw new BusinessException("订单状态不正确");
        }

        if(divMoney.getAmount().compareTo(order.getPrice()) > 0){
            throw new BusinessException("分账金额不正确");
        }

        //查找支付宝账户
        UserFundAccount primaryAccount = userFunAccountService.getPrimaryAlipayAccount(divMoney.getUserId());
        if(primaryAccount == null){
            throw new BusinessException("用户未绑定支付宝资金账户，分账失败");
        }

        if(primaryAccount.getAccountStatus() != AccountStatus.NORMAL){
            throw new BusinessException("用户绑定的支付宝账户状态不正常");
        }

        TransferMethod transferMethod = null;
        switch(primaryAccount.getAccountType()){
            case ALIPAY_USER_ID:
            case ALIPAY_LOGON_ID:
                transferMethod = TransferMethod.ALIPAY;
            break;
            default:
                throw new BusinessException("不支持的资金账户类型：" + primaryAccount.getAccountType());
        }

        //无论成功与否，直接标记已处理
        divMoney.setStatus(DivStatus.PROCESSED);
        divMoney.setProcessTime(LocalDateTime.now());


        if(divMoney.getTransferMoneyId() != null){
            //历史记录
            TransferMoneyInfo transferMoneyInfo = transferMoneyInfoRepo.findById(divMoney.getTransferMoneyId()).orElseThrow(new BusinessException("历史转账记录不存在"));
            //是否账户不重复
            if(transferMoneyInfo.getAccountNo().equals(primaryAccount.getAccountNo())){
                throw new BusinessException("不允许对重复的账户重新转账");
            }
        }

        //保存转账记录
        String tradeNo = String.valueOf(snowflakeIdWorker.nextId());
        TransferMoneyInfo.TransferMoneyInfoBuilder builder = TransferMoneyInfo.builder();
        builder.tradeNo(tradeNo).toUserId(divMoney.getUserId())
                .transferMethod(transferMethod)
                .accountType(primaryAccount.getAccountType().name())
                .accountNo(primaryAccount.getAccountNo())
                .accountName(primaryAccount.getAccountName())
                .amount(divMoney.getAmount())
                .payPlatform(divMoney.getPayPlatform())
                .reason(reason)
                .divMoneyId(divMoneyId);
        TransferMoneyInfo transferMoneyInfo = transferMoneyInfoRepo.save(builder.build());


        //记录转账记录ID
        divMoney.setTransferMoneyId(transferMoneyInfo.getId());

        try {
            JSONObject params = new JSONObject();
            params.put("out_trade_no", transferMoneyInfo.getTradeNo());
            Long amount = transferMoneyInfo.getAmount().multiply(new BigDecimal(100)).longValue();
            params.put("amount", amount);
            params.put("account", transferMoneyInfo.getAccountNo());
            params.put("account_type", transferMoneyInfo.getAccountType());
            params.put("account_name", transferMoneyInfo.getAccountName());
            //描述特定的业务场景，默认值为：DIRECT_TRANSFER
            //DIRECT_TRANSFER：单笔无密转账到支付宝，B2C现金红包
            //PERSONAL_COLLECTION：C2C现金红包-领红包
            params.put("biz_scene", "DIRECT_TRANSFER");
            params.put("title", reason);
            params.put("desc", "分润订单ID" + order.getId());

            JSONObject resultJson = ikudotpayClient.postJson("/openapi/pay/fund/aliTransfer", params);
            String transferOrderId = resultJson.getString("order_id");
            String transactionId = resultJson.getString("pay_fund_order_id");
            String transferDate = resultJson.getString("transfer_date");
            //SUCCESS:转账成功
            //FAILED:转账失败
            //PROCESSING:处理中
            String status = resultJson.getString("status");

            String resultStr = "默认成功";
            transferMoneyInfo.setTransferOrderId(transferOrderId);
            transferMoneyInfo.setTransactionId(transactionId);
            transferMoneyInfo.setTransferDate(transferDate);
            TransferStatus transferStatus = null;
            if("SUCCESS".equals(status)){
                transferStatus = TransferStatus.SUCCESS;
            }else if("FAILED".equals(status)){
                transferStatus = TransferStatus.FAILED;
                resultStr = "响应状态为失败：" + status;
                divMoney.setStatus(DivStatus.ERROR);
                divMoney.setTransferResult(resultStr);

            }else if("PROCESSING".equals(status)){
                transferStatus = TransferStatus.PROCESSING;
                resultStr = "处理中";
            }else{
                log.error("转账状态未知,交易订单：{}， 状态：{}" , transferMoneyInfo.getTradeNo(),  status);
            }

            transferMoneyInfo.setStatus(transferStatus);
            transferMoneyInfo.setResult(resultStr);
            divMoney.setTransferResult(resultStr);
            transferMoneyInfoRepo.save(transferMoneyInfo);
        }catch(Exception e){
            log.error("分润转账失败，分账记录ID:" + divMoneyId, e);
            transferMoneyInfo.setStatus(TransferStatus.FAILED);
            transferMoneyInfo.setResult(e.getMessage());
            divMoney.setStatus(DivStatus.ERROR);
            divMoney.setTransferResult(e.getMessage());
        }

        transferMoneyInfoRepo.save(transferMoneyInfo);
        divMoneyRepo.save(divMoney);

        return transferMoneyInfo;
    }

}
