package cn.com.ctop.finance.payment.service.impl;

import cn.com.ctop.common.module.entity.Advertiser;
import cn.com.ctop.common.module.entity.Product;
import cn.com.ctop.common.module.entity.Project;
import cn.com.ctop.common.module.entity.UserAllocation;
import cn.com.ctop.common.module.service.IMessageTemplate;
import cn.com.ctop.common.module.service.IProductService;
import cn.com.ctop.common.module.service.IProjectService;
import cn.com.ctop.common.module.service.ISendMessageService;
import cn.com.ctop.common.module.service.ISysUserService;
import cn.com.ctop.common.module.service.IUserAllocationService;
import cn.com.ctop.common.module.utils.Check;
import cn.com.ctop.finance.payment.entity.FinancePaymentPool;
import cn.com.ctop.finance.payment.entity.FinancePaymentRechargeAccount;
import cn.com.ctop.finance.payment.entity.FinancePaymentRechargeApplication;
import cn.com.ctop.finance.payment.entity.FinancePaymentRechargeApplicationRecord;
import cn.com.ctop.finance.payment.mapper.FinancePaymentRechargeApplicationMapper;
import cn.com.ctop.finance.payment.mapper.FinancePaymentRechargeApplicationRecordMapper;
import cn.com.ctop.finance.payment.service.IFinancePaymentPoolService;
import cn.com.ctop.finance.payment.service.IFinancePaymentRechargeAccountService;
import cn.com.ctop.finance.payment.service.IFinancePaymentRechargeApplicationService;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.system.entity.SysUser;
import org.jeecg.modules.ctop.service.IAdvertiserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * 充值申请表
 */
@Service
public class FinancePaymentRechargeApplicationServiceImpl extends ServiceImpl<FinancePaymentRechargeApplicationMapper, FinancePaymentRechargeApplication> implements IFinancePaymentRechargeApplicationService {

    @Autowired
    private IFinancePaymentPoolService financePaymentPoolService;
    @Autowired
    private IAdvertiserService advertiserService;
    @Autowired
    private IProductService productService;
    @Autowired
    private IProjectService projectService;
    @Autowired
    private ISysUserService userService;
    @Autowired
    private IUserAllocationService userAllocationService;
    @Autowired
    private IFinancePaymentRechargeAccountService rechargeAccountService;
    @Autowired
    private ISendMessageService sendMessageService;
    @Autowired
    private IMessageTemplate messageTemplate;
    @Autowired
    private FinancePaymentRechargeApplicationRecordMapper recordMapper;
    @Autowired
    private IFinancePaymentPoolService poolService;

    //财务审核角色ID
    public static final String FINANCIAL_REVIEW_ROLE_ID = "32825ea6b43cb61bffa09bf05ad69cf2";
    //财务角色ID
    public static final String FINANCIAL_ROLE_ID = "5f3ee6bbd66cbd2df404cdec4ad7e5a3";
    //媒介审核角色ID
    public static final String MEIDA_MANAGER_ROLE_ID = "4e9ba2fe611ef62a8ce1d4df086f94c3";


    @Override
    public Result<Object> queryPageList(FinancePaymentRechargeApplication recharge, Integer pageNo, Integer pageSize) {
        PageHelper.startPage(pageNo, pageSize);
        List<JSONObject> list = baseMapper.queryPageList(recharge);
        return Result.ok(new PageInfo<>(list));
    }

    @Override
    public Result<Object> queryRechargeAccountDetails(Long rechargeId) {
        return Result.ok(rechargeAccountService.queryByRechargeId(rechargeId));
    }

    @Override
    public Result add(JSONObject data) {
        try {
            JSONArray list = data.getJSONArray("list");
            FinancePaymentRechargeApplication recharge = JSONObject.parseObject(JSONObject.toJSONString(data), FinancePaymentRechargeApplication.class);
            List<String> advertiserIds = Arrays.asList(recharge.getAdvertiserId().split(","));
            Advertiser advertiser = advertiserService.getById(advertiserIds.get(0));
            if (!Check.isNull(advertiser)) {
                recharge.setAdvertiserName(advertiser.getName());
                data.put("advertiserName", advertiser.getName());
            }
            FinancePaymentPool pool = financePaymentPoolService.getIdByUniqueKey(recharge.getAdvertiserName(), recharge.getProductId(), recharge.getPaymentMedia(), recharge.getPaymentPort());
            if (Check.isNull(pool) || Check.isNull(list)) {
                return Result.error("数据异常");
            }
            SysUser user = userService.getById(recharge.getApplicanterId());
            if (!Check.isNull(user)) {
                recharge.setApplicanter(user.getRealname());
            }
            Product product = productService.getById(recharge.getProductId());
            if (!Check.isNull(product)) {
                recharge.setProductName(product.getProductName());
                data.put("productName", product.getProductName());
            }
            Project project = projectService.getById(recharge.getProjectId());
            if (!Check.isNull(project)) {
                recharge.setProjectName(project.getProjectName());
                data.put("projectName", project.getProjectName());
            }
            Date createTime = new Date();
            Thread.sleep(1000);
            //判断审核人和状态
            getReviewedRole(recharge);
            recharge.setPoolId(pool.getId());
            recharge.setCreateTime(new Date());
            recharge.setUpdateTime(null);
            this.save(recharge);
            //添加申请记录
            insertRecord(recharge.getId(), recharge.getApplicanterId(), "0", null, recharge.getFiles(), createTime);
            //添加充值账户信息
            List<FinancePaymentRechargeAccount> accountList = new ArrayList<>();
            String accountIds = "";
            BigDecimal displayAmount = new BigDecimal("0");
            for (int i = 0; i < list.size(); i++) {
                JSONObject obj = list.getJSONObject(i);
                obj.put("accountId",obj.getString("accountId").trim());
                FinancePaymentRechargeAccount account = new FinancePaymentRechargeAccount();
                account.setRechargeId(recharge.getId());
                account.setProjectId(recharge.getProjectId());
                account.setAccountId(obj.getString("accountId"));
                UserAllocation allocation = userAllocationService.getByAccountId(obj.getLong("accountId"));
                if (!Check.isNull(allocation)) {
                    account.setAccountName(allocation.getAuthName());
                    account.setProjectId(allocation.getProjectId());
                }
                JSONObject productObj = userAllocationService.getProductInfo(obj.getLong("accountId"));
                if (Check.isNull(productObj)) {
                    account.setProductId(recharge.getProductId());
                    account.setProductName(recharge.getProductName());
                } else {
                    account.setProductId(productObj.getLong("id"));
                    account.setProductName(productObj.getString("product_name"));
                }
                account.setCashAmount(obj.getBigDecimal("cashAmount"));
                account.setReceivedAmount(obj.getBigDecimal("receivedAmount"));
                displayAmount = displayAmount.add(obj.getBigDecimal("receivedAmount"));
                account.setRebateType(obj.getString("rebateType"));
                account.setRebateRate(obj.getDouble("rebateRate"));
                accountList.add(account);
                accountIds += obj.getLong("accountId") + "，";
            }
            rechargeAccountService.saveBatch(accountList);
            data.put("displayAmount", displayAmount);
            data.put("amends", recharge.getAmends());
            //消息通知内容
            String message = null;
            List<SysUser> users = null;
            if (recharge.getReviewederId().contains("financ")) {
                //财务
                message = messageTemplate.getFinancePaymentApplicationCWRechargeMessage(data);
                users = userService.getUserListByRoleId(FINANCIAL_REVIEW_ROLE_ID);
                users.addAll(userService.getUserListByRoleId(FINANCIAL_ROLE_ID));
                //财务审核时，同时发送消息告诉申请人，池子资金不足
                sendMessageService.sendMessage(recharge.getApplicanterId(),messageTemplate.getFinancePaymentApplicationRechargeMessage(data));
            } else {
                //媒介
                data.put("accountIds", accountIds.substring(0, accountIds.length() - 1));
                message = messageTemplate.getFinancePaymentApplicationMJRechargeMessage(data);
                users = userService.getUserListByRoleId(MEIDA_MANAGER_ROLE_ID);
            }
            for (SysUser u : users) {
                sendMessageService.sendMessage(u.getId(), message);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return Result.ok();
    }

    @Override
    public Result<Object> edit(JSONObject data) throws InterruptedException {
        JSONArray list = data.getJSONArray("list");
        FinancePaymentRechargeApplication recharge = JSONObject.parseObject(JSONObject.toJSONString(data), FinancePaymentRechargeApplication.class);
        FinancePaymentRechargeApplication oldRecharge = this.getById(recharge.getId());
        List<String> advertiserIds = Arrays.asList(recharge.getAdvertiserId().split(","));
        Advertiser advertiser = advertiserService.getById(advertiserIds.get(0));
        if (!Check.isNull(advertiser)) {
            recharge.setAdvertiserName(advertiser.getName());
            data.put("advertiserName", advertiser.getName());
        }
        FinancePaymentPool pool = financePaymentPoolService.getIdByUniqueKey(recharge.getAdvertiserName(), recharge.getProductId(), recharge.getPaymentMedia(), recharge.getPaymentPort());
        if (Check.isNull(pool) || Check.isNull(list)) {
            return Result.error("数据异常");
        }
        SysUser user = userService.getById(recharge.getApplicanterId());
        if (!Check.isNull(user)) {
            recharge.setApplicanter(user.getRealname());
        }
        Product product = productService.getById(recharge.getProductId());
        if (!Check.isNull(product)) {
            recharge.setProductName(product.getProductName());
            data.put("productName", product.getProductName());
        }
        Project project = projectService.getById(recharge.getProjectId());
        if (!Check.isNull(project)) {
            recharge.setProjectName(project.getProjectName());
            data.put("projectName", project.getProjectName());
        }
        //判断审核人和状态
        getReviewedRole(recharge);
        recharge.setPoolId(pool.getId());

        //添 拒绝记录
        insertRecord(recharge.getId(), oldRecharge.getReviewederId(), oldRecharge.getAuditStatus(), oldRecharge.getApprovalContent(), oldRecharge.getFiles(), oldRecharge.getUpdateTime());
        //添加申请记录 -1 退回修改
        insertRecord(recharge.getId(), recharge.getApplicanterId(), "-1", null, recharge.getFiles(), new Date());
        Thread.sleep(1000);

        this.updateById(recharge);

        BigDecimal displayAmount = new BigDecimal("0");

        //添加充值账户信息
        List<FinancePaymentRechargeAccount> accountList = new ArrayList<>();
        String accountIds = "";
        for (int i = 0; i < list.size(); i++) {
            JSONObject obj = list.getJSONObject(i);
            FinancePaymentRechargeAccount account = new FinancePaymentRechargeAccount();
            account.setRechargeId(recharge.getId());
            account.setProjectId(recharge.getProjectId());
            account.setAccountId(obj.getString("accountId"));
            UserAllocation acco = userAllocationService.getByAccountId(obj.getLong("accountId"));
            if (!Check.isNull(acco)) {
                account.setAccountName(acco.getAuthName());
            }
            account.setCashAmount(obj.getBigDecimal("cashAmount"));
            account.setReceivedAmount(obj.getBigDecimal("receivedAmount"));
            displayAmount = displayAmount.add(obj.getBigDecimal("receivedAmount"));
            account.setRebateType(obj.getString("rebateType"));
            account.setRebateRate(obj.getDouble("rebateRate"));
            accountList.add(account);
            accountIds += obj.getLong("accountId") + "，";
        }
        rechargeAccountService.delByRechargeId(recharge.getId());
        rechargeAccountService.saveBatch(accountList);

        data.put("displayAmount", displayAmount);
        data.put("amends", recharge.getAmends());
        //消息通知内容
        String message = null;
        List<SysUser> users = null;
        if (recharge.getReviewederId().contains("financ")) {
            //财务
            message = messageTemplate.getFinancePaymentApplicationCWRechargeMessage(data);
            users = userService.getUserListByRoleId(FINANCIAL_REVIEW_ROLE_ID);
            users.addAll(userService.getUserListByRoleId(FINANCIAL_ROLE_ID));
        } else {
            //媒介
            data.put("accountIds", accountIds.substring(0, accountIds.length() - 1));
            message = messageTemplate.getFinancePaymentApplicationMJRechargeMessage(data);
            users = userService.getUserListByRoleId(MEIDA_MANAGER_ROLE_ID);
        }
        for (SysUser u : users) {
            sendMessageService.sendMessage(u.getId(), message);
        }
        return Result.ok();
    }

    @Override
    public Result<Object> updateStatus(JSONObject data) {
        JSONArray list = data.getJSONArray("list");
        FinancePaymentRechargeApplication recharge = JSONObject.parseObject(JSONObject.toJSONString(data), FinancePaymentRechargeApplication.class);
        FinancePaymentRechargeApplication oldRecharge = this.getById(recharge.getId());

        if (Check.isNull(oldRecharge)) {
            return Result.error("未查询到申请");
        }
        String auditStatus = recharge.getAuditStatus();//1-待审核、2-待充值、3-充值完成、4-临时充值、5-审核拒绝
        if ("2".equals(auditStatus)) {
            recharge.setReviewederId("meidaManager");
            recharge.setRevieweder("-");
            //添加审核记录 1:财务审核完成
            insertRecord(recharge.getId(), recharge.getUserId(), "6", recharge.getApprovalContent(), recharge.getFiles(), new Date());
            JSONObject oldData = JSONObject.parseObject(JSONObject.toJSONString(oldRecharge)).toJavaObject(JSONObject.class);
            oldData.put("amends", oldRecharge.getAmends());
            JSONObject amount = rechargeAccountService.queryAmounts(recharge.getId());
            if (!Check.isNull(amount)) {
                oldData.put("accountIds", amount.getString("accountIds"));
                oldData.put("totalAmount", amount.getString("cashAmount"));
                oldData.put("displayAmount", amount.getString("displayAmount"));
            }
            String message = messageTemplate.getFinancePaymentApplicationMJRechargeMessage(oldData);
            List<SysUser> users = userService.getUserListByRoleId(MEIDA_MANAGER_ROLE_ID);
            for (SysUser u : users) {
                sendMessageService.sendMessage(u.getId(), message);
            }
            this.updateById(recharge);
        } else if ("3".equals(auditStatus) || "4".equals(auditStatus)) {
            recharge.setReviewederId(recharge.getUserId());
            SysUser user = userService.getById(recharge.getUserId());
            if (!Check.isNull(user)) {
                recharge.setRevieweder(user.getRealname());
            }
            this.updateById(recharge);
            poolService.reduce(oldRecharge, null);

            JSONObject oldData = JSONObject.parseObject(JSONObject.toJSONString(oldRecharge)).toJavaObject(JSONObject.class);
            oldData.put("amends", oldRecharge.getAmends());
            JSONObject amount = rechargeAccountService.queryAmounts(recharge.getId());
            if (!Check.isNull(amount)) {
                oldData.put("accountIds", amount.getString("accountIds"));
                oldData.put("totalAmount", amount.getString("cashAmount"));
                oldData.put("displayAmount", amount.getString("displayAmount"));
            }
            String message = messageTemplate.getRechargedSuccessfullyMessage(oldData);
            sendMessageService.sendMessage(oldRecharge.getApplicanterId(), message);

        } else if ("5".equals(auditStatus)) {
            if ("4".equals(recharge.getAuditStatus())) {
                poolService.add(oldRecharge, null);
            }
            recharge.setFiles(Check.isNull(recharge.getFiles()) ? "-" : recharge.getFiles());
            recharge.setReviewederId(recharge.getUserId());
            SysUser user = userService.getById(recharge.getUserId());
            if (!Check.isNull(user)) {
                recharge.setRevieweder(user.getRealname());
            }
            this.updateById(recharge);
            //添加审核记录
            insertRecord(recharge.getId(), recharge.getUserId(), oldRecharge.getAuditStatus(), oldRecharge.getApprovalContent(), oldRecharge.getFiles(), oldRecharge.getUpdateTime());
            JSONObject oldData = JSONObject.parseObject(JSONObject.toJSONString(oldRecharge)).toJavaObject(JSONObject.class);
            oldData.put("amends", oldRecharge.getAmends());
            String failMessage = null;
            List<SysUser> users = null;
            if (oldRecharge.getReviewederId().contains("financ")) {
                failMessage = messageTemplate.getFinancePaymentApplicationCWRechargeRefuseMessage(oldData);
                users = userService.getUserListByRoleId(FINANCIAL_REVIEW_ROLE_ID);
                users.addAll(userService.getUserListByRoleId(FINANCIAL_ROLE_ID));
            } else {
                failMessage = messageTemplate.getFinancePaymentApplicationMJRechargeRefuseMessage(oldData);
                users = userService.getUserListByRoleId(MEIDA_MANAGER_ROLE_ID);
            }
            for (SysUser u : users) {
                sendMessageService.sendMessage(u.getId(), failMessage);
            }
        }
        return Result.ok();
    }

    @Override
    public Result<Object> updateTemporaryFiles(JSONObject data) {
        FinancePaymentRechargeApplication recharge = JSONObject.parseObject(JSONObject.toJSONString(data), FinancePaymentRechargeApplication.class);
        FinancePaymentRechargeApplication oldApplication = this.getById(recharge.getId());
        if (Check.isNull(oldApplication)) {
            return Result.error("未查询到申请");
        }
        String auditStatus = oldApplication.getAuditStatus();//4-临时通过
        if ("4".equals(auditStatus)) {
            recharge.setAuditStatus("3");
            recharge.setApprovalContent(Check.isNull(recharge.getApprovalContent()) ? "-" : recharge.getApprovalContent());
            recharge.setReviewederId(recharge.getUserId());
            SysUser user = userService.getById(recharge.getUserId());
            if (!Check.isNull(user)) {
                recharge.setRevieweder(user.getRealname());
            }
            this.updateById(recharge);
            //添加审核记录
            insertRecord(recharge.getId(), oldApplication.getReviewederId(), auditStatus, oldApplication.getApprovalContent(), oldApplication.getFiles(), oldApplication.getUpdateTime());
        }
        return Result.ok();
    }

    @Override
    public Result<Object> queryAuditProcess(Long id) {
        return Result.ok(baseMapper.queryAuditProcess(id));
    }

    @Override
    public List<JSONObject> queryAccountList(FinancePaymentRechargeApplication recharge) {
        return baseMapper.queryAccountList(recharge);
    }

    private void getReviewedRole(FinancePaymentRechargeApplication recharge) {
        String financialReview = recharge.getFinancialReview();
        if (!Check.isNull(financialReview) && "1".equals(financialReview)) {
            recharge.setReviewederId("financ");
            recharge.setRevieweder("-");
            recharge.setAuditStatus("1");//待审核
        } else {
            //媒介
            recharge.setReviewederId("meidaManager");
            recharge.setRevieweder("-");
            recharge.setAuditStatus("2");//待充值
        }
    }

    private void insertRecord(Long rechargeId, String operatorId, String status, String txt, String files, Date time) {
        if ("1".equals(status) || "2".equals(status)) {
            return;
        }
        FinancePaymentRechargeApplicationRecord record = new FinancePaymentRechargeApplicationRecord();
        record.setRechargeId(rechargeId);
        record.setReviewederId(operatorId);
        record.setAuditStatus(status);
        record.setApprovalContent(txt);
        record.setFiles(files);
        record.setCreateTime(time);
        recordMapper.insert(record);
    }

}
