package com.crm.manager.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.crm.manager.dao.mapper.SalesSalaryRecordMapper;
import com.crm.manager.dao.mapper.UserInfoDao;
import com.crm.manager.service.AccountInfoFeignService;
import com.crm.manager.service.AccountInfoService;
import com.crm.manager.service.SalesSalaryRecordService;
import com.crm.manager.service.UserInfoService;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.PrefixEnum;
import com.crm.rely.backend.core.dto.base.BaseResultWithPagerDto;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.sales.SalesCommissionRuleDto;
import com.crm.rely.backend.core.dto.sales.SalesSalaryRecordDto;
import com.crm.rely.backend.core.entity.finance.balance.FinanceBalanceAddEntity;
import com.crm.rely.backend.core.entity.sales.SalesBalanceWithdrawalEntity;
import com.crm.rely.backend.core.entity.sales.SalesSalaryRecordAddEntity;
import com.crm.rely.backend.core.entity.sales.SalesSalaryRecordListEntity;
import com.crm.rely.backend.core.enums.BalanceOperateType;
import com.crm.rely.backend.core.enums.SalesSalaryRecordType;
import com.crm.rely.backend.core.pojo.table.FinanceBalanceTable;
import com.crm.rely.backend.core.pojo.table.SalesCommissionRuleTable;
import com.crm.rely.backend.core.pojo.table.SalesSalaryRecordTable;
import com.crm.rely.backend.core.pojo.table.UserInfoTable;
import com.crm.rely.backend.core.pojo.view.SalesSalaryRecordView;
import com.crm.rely.backend.exception.ServiceException;
import com.crm.rely.backend.service.MqSendService;
import com.crm.rely.backend.util.FormatPage;
import com.crm.rely.backend.util.GetRandom;
import com.google.common.collect.Lists;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

@Service
public class SalesSalaryRecordServiceImpl implements SalesSalaryRecordService {

    private final Logger logger = LoggerFactory.getLogger(SalesSalaryRecordServiceImpl.class);

    @Autowired
    private SalesSalaryRecordMapper salesSalaryRecordMapper;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private UserInfoDao userInfoDao;
    @Autowired
    private MqSendService mqSendService;
    @Autowired
    private AccountInfoService accountInfoService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(SalesSalaryRecordAddEntity entity) throws ServiceException {
        SalesSalaryRecordTable table = SalesSalaryRecordTable.getInstance();
        BeanUtils.copyProperties(entity, table);
        table.setRecordType(2);

        UserInfoTable userInfoTable = userInfoService.getDataById(entity.getSalesId());
        if (userInfoTable == null) {
            throw new ServiceException(Constants.INFO_NOT_FOUND);
        }

        table.setSalesNo(userInfoTable.getIbNo());
        salesSalaryRecordMapper.save(table);

        //更新销售余额
        Float amount = Math.abs(entity.getAmount());
        if (BalanceOperateType.CUT.getCode().equals(entity.getOperateType())) {
            amount = amount * -1;
        }
        entity.setAmount(amount);
        userInfoService.addBalance(entity.getSalesId(), entity.getAmount());
    }

    @Override
    public SalesSalaryRecordDto searchById(Long id) throws ServiceException {
        SalesSalaryRecordView view = salesSalaryRecordMapper.findOne(id);
        return convertViewToDto(view);
    }

    @Override
    public BaseResultWithPagerDto<List<SalesSalaryRecordDto>> searchList(SalesSalaryRecordListEntity entity) throws ServiceException {

        Integer count = salesSalaryRecordMapper.countSearch(entity);
        PageDto pageDto = FormatPage.format(entity.getPage(), count);
        if (count == null || count == 0) {
            return new BaseResultWithPagerDto<>(Constants.SUCCESS_CODE, Constants.SEARCH_SUCCESS, pageDto);
        }

        List<SalesSalaryRecordView> views = salesSalaryRecordMapper.listSearch(entity);
        List<SalesSalaryRecordDto> dtos = Lists.newArrayList();
        for (SalesSalaryRecordView view : views) {
            dtos.add(convertViewToDto(view));
        }

        return new BaseResultWithPagerDto<>(Constants.SUCCESS_CODE, Constants.SEARCH_SUCCESS, pageDto, dtos);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void salesBalanceWithdrawal(SalesBalanceWithdrawalEntity entity) throws ServiceException {
        try {
            UserInfoTable userInfoTable = userInfoDao.getDataById(entity.getSalesId());
            if (userInfoTable == null) {
                throw new ServiceException(Constants.INFO_NOT_FOUND);
            }

            float balance = userInfoTable.getBalance();
            if (balance < entity.getAmount()) {
                throw new ServiceException("insufficient_funds");
            }

            //交易是否存在账户限制
            if (!accountInfoService.loginExistsByPlatform(userInfoTable.getSalaryLogin(), userInfoTable.getSalaryPlatform())) {
                throw new ServiceException(Constants.LOGIN_NOT_EXIST_ERROR);
            }


            entity.setSalaryLogin(userInfoTable.getSalaryLogin());
            entity.setSalaryPlatform(userInfoTable.getSalaryPlatform());
            entity.setSerial(GetRandom.getOrderNo("SW"));
            //金额打入交易账户
            FinanceBalanceAddEntity financeBalanceAddEntity = new FinanceBalanceAddEntity();
            financeBalanceAddEntity.setAmount(BigDecimal.valueOf(entity.getAmount()));
            financeBalanceAddEntity.setSerial(entity.getSerial());
            financeBalanceAddEntity.setLogin(entity.getSalaryLogin());
            mqSendService.send(Constants.FINANCE_BALANCE_INFO, JSONObject.toJSONString(financeBalanceAddEntity));
            //扣款记录
            SalesSalaryRecordTable table = SalesSalaryRecordTable.getInstance();
            table.setSalesId(entity.getSalesId());
            table.setAmount(entity.getAmount());
            table.setRecordType(SalesSalaryRecordType.WITHDRAWAL.getCode());
            table.setOperateType(BalanceOperateType.CUT.getCode());
            table.setAddTime(entity.getAddTime());
            table.setAddUser(entity.getAddUser());
            table.setSerial(entity.getSerial());
            table.setStatus(1);
            table.setSalaryLogin(userInfoTable.getSalaryLogin());
            table.setSalesNo(userInfoTable.getIbNo());
            salesSalaryRecordMapper.save(table);
            //扣除余额
            userInfoTable.setBalance(balance - entity.getAmount());
            userInfoDao.updateUserBalanceById(userInfoTable);
        } catch (Exception e) {
            logger.error(e.getMessage());
            throw ServiceException.exception(e.getMessage());
        }

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void salesBalanceCallback(FinanceBalanceTable financeBalanceTable) throws ServiceException {
        SalesSalaryRecordTable table = salesSalaryRecordMapper.getBySerial(financeBalanceTable.getSerial());
        if (table == null) {
            return;
        }

        table.setStatus(financeBalanceTable.getTradeStatus());
        table.setNote(financeBalanceTable.getErrNote());
        table.setModifyTime(new Date());
        salesSalaryRecordMapper.updateStatusById(table);
        /*
            如果失败
         */
        if (financeBalanceTable.getTradeStatus() != 2) {
            /*
                返还扣除的金额
             */
            UserInfoTable userInfoTable = userInfoService.getDataById(table.getSalesId());
            if (userInfoTable == null) return;
            userInfoTable.setBalance((userInfoTable.getBalance() == null ? 0F : userInfoTable.getBalance()) + table.getAmount());
            userInfoDao.updateUserBalanceById(userInfoTable);

        }
    }

    private SalesSalaryRecordDto convertViewToDto(SalesSalaryRecordView view) {
        SalesSalaryRecordDto dto = new SalesSalaryRecordDto();
        BeanUtils.copyProperties(view, dto);
        dto.setRecordTypeName(SalesSalaryRecordType.matchCode(view.getRecordType()).getDesc());
        dto.setOperateTypeName(BalanceOperateType.matchCode(view.getOperateType()).getDesc());
        return dto;
    }
}
