package com.huiju.estateagents.redpack.service.impl;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.huiju.estateagents.center.sysUser.entity.SysUser;
import com.huiju.estateagents.center.sysUser.mapper.SysUserMapper;
import com.huiju.estateagents.common.NumberUtils;
import com.huiju.estateagents.redpack.service.ITaOrgOrderService;
import org.apache.commons.collections.CollectionUtils;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huiju.estateagents.base.ResponseBean;
import com.huiju.estateagents.center.taUser.entity.TaUser;
import com.huiju.estateagents.center.taUser.mapper.TaUserMapper;
import com.huiju.estateagents.common.CommConstant;
import com.huiju.estateagents.common.CommonUtils;
import com.huiju.estateagents.common.SMSUtils;
import com.huiju.estateagents.common.StringUtils;
import com.huiju.estateagents.entity.SysSmsSetting;
import com.huiju.estateagents.mapper.SysSmsSettingMapper;
import com.huiju.estateagents.redpack.entity.TaOrgAccount;
import com.huiju.estateagents.redpack.entity.TaOrgAccountBlocked;
import com.huiju.estateagents.redpack.entity.TaOrgAccountCertificate;
import com.huiju.estateagents.redpack.entity.TaOrgAccountDetailedList;
import com.huiju.estateagents.redpack.entity.TaOrgOrder;
import com.huiju.estateagents.redpack.entity.TaOrgOrderDetail;
import com.huiju.estateagents.redpack.entity.TaOrgRefundApplication;
import com.huiju.estateagents.redpack.mapper.TaOrgAccountBlockedMapper;
import com.huiju.estateagents.redpack.mapper.TaOrgAccountCertificateMapper;
import com.huiju.estateagents.redpack.mapper.TaOrgAccountDetailedListMapper;
import com.huiju.estateagents.redpack.mapper.TaOrgAccountMapper;
import com.huiju.estateagents.redpack.mapper.TaOrgOrderDetailMapper;
import com.huiju.estateagents.redpack.mapper.TaOrgOrderMapper;
import com.huiju.estateagents.redpack.mapper.TaOrgRefundApplicationMapper;
import com.huiju.estateagents.redpack.service.ITaOrgAccountService;
import com.huiju.estateagents.sample.entity.TaContact;
import com.huiju.estateagents.sample.mapper.TaContactMapper;

import io.swagger.models.auth.In;

/**
 * <p>
 * 系统账户表  服务实现类
 * </p>
 *
 * @author fxf
 * @since 2020-06-03
 */
@Service
public class TaOrgAccountServiceImpl extends ServiceImpl<TaOrgAccountMapper, TaOrgAccount> implements ITaOrgAccountService {

    @Autowired
    private TaOrgAccountMapper taOrgAccountMapper;

    @Autowired
    private TaOrgOrderMapper taOrgOrderMapper;

    @Autowired
    private TaOrgOrderDetailMapper taOrgOrderDetailMapper;

    @Autowired
    private TaOrgAccountCertificateMapper taOrgAccountCertificateMapper;

    @Autowired
    private TaOrgAccountDetailedListMapper taOrgAccountDetailedListMapper;

    @Autowired
    private TaOrgRefundApplicationMapper taOrgRefundApplicationMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private ITaOrgOrderService iTaOrgOrderService;

    @Autowired
    private TaContactMapper taContactMapper;

    @Autowired
    SysSmsSettingMapper sysSmsSettingMapper;

    @Autowired
    private TaOrgAccountBlockedMapper taOrgAccountBlockedMapper;

    @Autowired
    SMSUtils smsUtils;

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public ResponseBean rechargeAccount(String accountId, TaOrgAccount taOrgAccount, Integer orgId, Integer userId) {
        ResponseBean responseBean = new ResponseBean();

        //更新系统账户充值金额
        TaOrgAccount rechargeAccount = assembleRechargeAccount(accountId, taOrgAccount);
        synchronized (this) {
            taOrgAccountMapper.updateById(rechargeAccount);
        }

        //新增订单记录
        TaOrgOrder taOrgOrder = assembleTaOrgOrder(orgId, taOrgAccount.getRechargeAmount(), userId, CommConstant.ITEM_TYPE_RECHARGE);
        int taOrgOrderInsertResult = taOrgOrderMapper.insert(taOrgOrder);

        //新增关联订单明细
        TaOrgOrderDetail taOrgOrderDetail = assembleTaOrgOrderDetail(taOrgOrder.getOrderId(), orgId, taOrgAccount.getRechargeAmount(), CommConstant.ITEM_TYPE_RECHARGE);
        int taOrgOrderDetailInsertResult = taOrgOrderDetailMapper.insert(taOrgOrderDetail);

        //新增账户消费流水记录
        TaOrgAccountDetailedList taOrgAccountDetailedList = assembleAccountDetailList(accountId, orgId, taOrgAccount, taOrgOrder.getOrderId(), userId, CommConstant.ITEM_TYPE_RECHARGE);
        int taOrgAccountDetailedListInsertResult = taOrgAccountDetailedListMapper.insert(taOrgAccountDetailedList);

        //插入凭证记录
        taOrgAccount.setAccountId(accountId);
        if (CollectionUtils.isNotEmpty(taOrgAccount.getCertificateList())) {
            List<TaOrgAccountCertificate> taOrgAccountCertificateList = assembleAccountCertificate(orgId, taOrgAccount, taOrgAccountDetailedList.getSerialNo(), taOrgOrder.getOrderId(), userId, CommConstant.ITEM_TYPE_RECHARGE);
            taOrgAccountCertificateList.forEach(e -> {
                taOrgAccountCertificateMapper.insert(e);
            });
        }

        if (taOrgOrderInsertResult < 1 ||
                taOrgOrderDetailInsertResult < 1 ||
                taOrgAccountDetailedListInsertResult < 1) {
            responseBean.addError("充值失败");
            return responseBean;
        }

        List<TaContact> taContacts = selectSmsContactUser();
        if (CollectionUtils.isNotEmpty(taContacts)){
            TaContact taContact = taContacts.get(0);
            String[] smsParams = {"业务平台充值提醒", taOrgOrder.getTradeNo()};
            // 短信发送
            sendSmsMessage(taContact.getPhone(), CommConstant.ITEM_TYPE_RECHARGE, smsParams);
        }

        return responseBean;
    }

    @Override
    @Transactional(rollbackFor = {RuntimeException.class})
    public ResponseBean refundAccount(String accountId, TaOrgAccount taOrgAccount, Integer orgId, Integer userId) {
        ResponseBean responseBean = new ResponseBean();

        //更新系统账户余额
        TaOrgAccount selectOneAccount = selectTaOrgAccountById(accountId);
        if (selectOneAccount.getAvailableBalance() < NumberUtils.yuanToFen(taOrgAccount.getRefundAmount())) {
            responseBean.addError("退款额不能大于余额");
            return responseBean;
        }
        TaOrgAccount refundAccount = assembleRefundAccount(accountId, taOrgAccount);
        taOrgAccountMapper.updateById(refundAccount);

        //新增订单记录
        TaOrgOrder taOrgOrder = assembleTaOrgOrder(orgId, taOrgAccount.getRefundAmount(), userId, CommConstant.ITEM_TYPE_REFUND);
        int taOrgOrderInsertResult = taOrgOrderMapper.insert(taOrgOrder);

        //新增关联订单明细
        TaOrgOrderDetail taOrgOrderDetail = assembleTaOrgOrderDetail(taOrgOrder.getOrderId(), orgId, taOrgAccount.getRefundAmount(), CommConstant.ITEM_TYPE_REFUND);
        int taOrgOrderDetailInsertResult = taOrgOrderDetailMapper.insert(taOrgOrderDetail);

        //新增账户消费流水
        TaOrgAccountDetailedList taOrgAccountDetailedList = assembleAccountDetailList(accountId, orgId, taOrgAccount, taOrgOrder.getOrderId(), userId, CommConstant.ITEM_TYPE_REFUND);
        int taOrgAccountDetailedListInsertResult = taOrgAccountDetailedListMapper.insert(taOrgAccountDetailedList);

        //插入凭证记录
        taOrgAccount.setAccountId(accountId);
        if (CollectionUtils.isNotEmpty(taOrgAccount.getCertificateList())) {
            List<TaOrgAccountCertificate> taOrgAccountCertificateList = assembleAccountCertificate(orgId, taOrgAccount, taOrgAccountDetailedList.getSerialNo(), taOrgOrder.getOrderId(), userId, CommConstant.ITEM_TYPE_REFUND);
            taOrgAccountCertificateList.forEach(e -> {
                taOrgAccountCertificateMapper.insert(e);
            });
        }

        if (taOrgOrderInsertResult < 1 ||
                taOrgOrderInsertResult < 1 ||
                taOrgOrderDetailInsertResult < 1 ||
                taOrgAccountDetailedListInsertResult < 1) {
            responseBean.addError("退费失败");
            return responseBean;
        }

        List<TaContact> taContacts = selectSmsContactUser();
        if (CollectionUtils.isNotEmpty(taContacts)){
            TaContact taContact = taContacts.get(0);
            String[] smsParams = {"业务平台退款申请", taOrgOrder.getTradeNo()};
            // 短信发送
            sendSmsMessage(taContact.getPhone(), CommConstant.ITEM_TYPE_REFUND, smsParams);
        }

        return responseBean;
    }

    @Override
    public TaOrgAccount getOrgAccountById(Integer orgId) {
        ResponseBean responseBean = new ResponseBean<>();
        TaOrgAccount taOrgAccount = taOrgAccountMapper.getOrgAccountById(orgId);

        //查询总充值金额
        Integer totalRechargeAmount = taOrgOrderMapper.countTotalRechargeAmount(orgId);
        taOrgAccount.setTotalRechargeAmount(totalRechargeAmount);

        //查询退款冻结额
        Integer totalBlockAmount = taOrgAccountBlockedMapper.countTotalBlockAmount(orgId);
        taOrgAccount.setRefundBlockedAmount(totalBlockAmount);

        //账户余额=总充值金额-已消费金额-已退款额-退款冻结额
        Integer balance = totalRechargeAmount - taOrgAccount.getPurchaseAmount() - taOrgAccount.getTotalRefund() - totalBlockAmount;
        taOrgAccount.setRealBalance(balance);

        return taOrgAccount;
    }

    @Override
    public ResponseBean getOrgAccountInfoByOrgId(Integer orgId) {
        ResponseBean responseBean = new ResponseBean();

        QueryWrapper<TaOrgAccount> orgAccountQueryWrapper = new QueryWrapper<>();
        orgAccountQueryWrapper.eq("org_id", orgId);
        orgAccountQueryWrapper.eq("status", CommConstant.STATUS_NORMAL);
        TaOrgAccount orgAccount = getOne(orgAccountQueryWrapper);
        if (orgAccount == null) {
            responseBean.addError("fail");
            return responseBean;
        }

        // 计算退款冻结金额
        orgAccount.setRefundBlockedAmount(taOrgRefundApplicationMapper.countRefundBlockedAmount(orgId));
        orgAccount.setTotalRechargeAmount(taOrgOrderMapper.countTotalRechargeAmount(orgId));
        responseBean.addSuccess(orgAccount);
        return responseBean;
    }

    /**
     * 构造充值账户
     *
     * @param accountId
     * @param taOrgAccount
     * @return
     */
    private TaOrgAccount assembleRechargeAccount(String accountId, TaOrgAccount taOrgAccount) {
        TaOrgAccount selectOneAccount = selectTaOrgAccountById(accountId);

        TaOrgAccount rechargeAccount = new TaOrgAccount();
        rechargeAccount.setAccountId(accountId);
        rechargeAccount.setAvailableBalance(selectOneAccount.getAvailableBalance() + NumberUtils.yuanToFen(taOrgAccount.getRechargeAmount()));
        rechargeAccount.setRealBalance(selectOneAccount.getRealBalance() + NumberUtils.yuanToFen(taOrgAccount.getRechargeAmount()));
        rechargeAccount.setModifyDate(LocalDateTime.now());

        return rechargeAccount;
    }

    /**
     * 构造交易凭证信息
     *
     * @param orgId
     * @param taOrgAccount
     * @param accountSerialNo
     * @param orderId
     * @param userId
     * @return
     */
    public List<TaOrgAccountCertificate> assembleAccountCertificate(Integer orgId, TaOrgAccount taOrgAccount, Integer accountSerialNo, String orderId, Integer userId, String consumeType) {
        SysUser taUser = selectUserById(userId);
        List<TaOrgAccountCertificate> taOrgAccountCertificateList = new ArrayList<>();

        taOrgAccount.getCertificateList().forEach(e -> {
            TaOrgAccountCertificate taOrgAccountCertificate = new TaOrgAccountCertificate();
            taOrgAccountCertificate.setOrgId(orgId);
            taOrgAccountCertificate.setAccountId(taOrgAccount.getAccountId());
            taOrgAccountCertificate.setAccountSerialNo(accountSerialNo);
            taOrgAccountCertificate.setOrderId(orderId);
            taOrgAccountCertificate.setConsumptionType(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? CommConstant.ITEM_TYPE_RECHARGE : CommConstant.ITEM_TYPE_REFUND);
            taOrgAccountCertificate.setRemark(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? "线下缴费" : "线下退费");
            taOrgAccountCertificate.setUrl(e);
            taOrgAccountCertificate.setCreateDate(LocalDateTime.now());
            taOrgAccountCertificate.setUserId(userId);
            taOrgAccountCertificate.setUserName(taUser.getUserName());
            taOrgAccountCertificateList.add(taOrgAccountCertificate);
        });

        return taOrgAccountCertificateList;
    }

    /**
     * 构造订单
     *
     * @param orgId
     * @param amount
     * @param userId
     * @return
     */
    private TaOrgOrder assembleTaOrgOrder(Integer orgId, String amount, Integer userId, String consumeType) {

        SysUser taUser = selectUserById(userId);
        TaOrgOrder taOrgOrder = new TaOrgOrder();
        taOrgOrder.setOrgId(orgId);
        taOrgOrder.setTradeNo(CommonUtils.generateTradeNo(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? CommConstant.RECHARGE : CommConstant.REFUND));
        taOrgOrder.setAmount(NumberUtils.yuanToFen(amount));
        taOrgOrder.setCreateDate(LocalDateTime.now());
        taOrgOrder.setPayDate(LocalDateTime.now());
        taOrgOrder.setExpiryDate(LocalDateTime.now());
        taOrgOrder.setRemark(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? "线下账户缴费" : "线下账户退费");
        taOrgOrder.setTradingStatus(CommConstant.TRADING_STATUS_SUCCESS);
        taOrgOrder.setIsOffline(true);
        taOrgOrder.setUserId(userId);
        taOrgOrder.setUserName(taUser.getUserName());

        return taOrgOrder;
    }

    /**
     * 构造交订单详情信息
     *
     * @param orderId
     * @param orgId
     * @param amount
     * @return
     */
    private TaOrgOrderDetail assembleTaOrgOrderDetail(String orderId, Integer orgId, String amount, String consumeType) {
        TaOrgOrderDetail taOrgOrderDetail = new TaOrgOrderDetail();

        taOrgOrderDetail.setOrderId(orderId);
        taOrgOrderDetail.setOrgId(orgId);
        taOrgOrderDetail.setItemType(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? CommConstant.ITEM_TYPE_RECHARGE : CommConstant.ITEM_TYPE_REFUND);
        taOrgOrderDetail.setAmount(NumberUtils.yuanToFen(amount));

        return taOrgOrderDetail;
    }

    /**
     * 构造消费流水记录
     *
     * @param orgId
     * @param taOrgAccount
     * @param orderId
     * @param userId
     * @return
     */
    private TaOrgAccountDetailedList assembleAccountDetailList(String accountId, Integer orgId, TaOrgAccount taOrgAccount, String orderId, Integer userId, String consumeType) {

        SysUser taUser = selectUserById(userId);
        TaOrgAccountDetailedList taOrgAccountDetailed = new TaOrgAccountDetailedList();
        taOrgAccountDetailed.setAccountId(accountId);
        taOrgAccountDetailed.setOrgId(orgId);
        taOrgAccountDetailed.setAmount(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? NumberUtils.yuanToFen(taOrgAccount.getRechargeAmount()) : NumberUtils.yuanToFen(taOrgAccount.getRefundAmount()));
        //1收入,-1支出
        taOrgAccountDetailed.setSignType(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? CommConstant.STATUS_NORMAL : CommConstant.STATUS_DELETE);
        taOrgAccountDetailed.setRemark(CommConstant.ITEM_TYPE_RECHARGE.equals(consumeType) ? "线下账户缴费" : "线下账户退费");
        taOrgAccountDetailed.setOrderId(orderId);
        taOrgAccountDetailed.setUserId(userId);
        taOrgAccountDetailed.setUserName(taUser.getUserName());

        return taOrgAccountDetailed;
    }

    /**
     * 构造退费账户
     *
     * @param accountId
     * @param taOrgAccount
     * @return
     */
    private TaOrgAccount assembleRefundAccount(String accountId, TaOrgAccount taOrgAccount) {
        TaOrgAccount selectOneAccount = selectTaOrgAccountById(accountId);

        TaOrgAccount refundAccount = new TaOrgAccount();
        refundAccount.setAccountId(accountId);
        refundAccount.setAvailableBalance(selectOneAccount.getAvailableBalance() - NumberUtils.yuanToFen(taOrgAccount.getRefundAmount()));
        refundAccount.setRealBalance(selectOneAccount.getRealBalance() - NumberUtils.yuanToFen(taOrgAccount.getRefundAmount()));
        refundAccount.setTotalRefund(NumberUtils.yuanToFen(taOrgAccount.getRefundAmount()) + selectOneAccount.getTotalRefund());
        refundAccount.setModifyDate(LocalDateTime.now());

        return refundAccount;
    }

    public TaOrgAccount selectTaOrgAccountById(String accountId) {
        QueryWrapper<TaOrgAccount> selectOneQuery = new QueryWrapper<>();
        selectOneQuery.eq("account_id", accountId);
        TaOrgAccount selectOneAccount = taOrgAccountMapper.selectOne(selectOneQuery);
        return selectOneAccount;
    }

    public SysUser selectUserById(Integer userId) {
        //获取操作人
        QueryWrapper<SysUser> sysUserQueryWrapper = new QueryWrapper<>();
        sysUserQueryWrapper.eq("user_id", userId);
        SysUser taUser = sysUserMapper.selectOne(sysUserQueryWrapper);
        return taUser;
    }

    @Override
    public String sendSmsMessage(String tel, String type, String[] params) {
        if (StringUtils.isEmpty(tel) || StringUtils.isEmpty(type)) {
            return "短信发送失败: 没有手机号或者短信模板";
        }

        QueryWrapper<SysSmsSetting> query = new QueryWrapper<>();
        query.eq("sms_type", type);
        query.eq("status", CommConstant.STATUS_NORMAL);
        query.last("limit 1");

        SysSmsSetting smsSetting = sysSmsSettingMapper.selectOne(query);
        if (null == smsSetting) {

            // TODO 写消息发送日志

            return "没有设置有效的【" + type + "】短信模板";
        }

        boolean success = smsUtils.sendMessage(smsSetting.getTplCode(), tel, params);

        // TODO 写消息发送日志

        return success ? null : "短信发送失败";
    }

    @Override
    public List<TaContact> selectSmsContactUser(){
        QueryWrapper<TaContact> taContactQueryWrapper = new QueryWrapper<>();
        taContactQueryWrapper.eq("contact_Type", CommConstant.CONTACT_FINANCE);
        taContactQueryWrapper.ne("status", CommConstant.STATUS_DELETE);
        List<TaContact> taContacts = taContactMapper.selectList(taContactQueryWrapper);
        return taContacts;
    }
}
