package com.hai.service.impl;

import com.hai.common.exception.ErrorCode;
import com.hai.common.exception.ErrorHelp;
import com.hai.common.exception.SysCode;
import com.hai.common.security.UserCenter;
import com.hai.common.utils.BankNumberUtil;
import com.hai.common.utils.RedisUtil;
import com.hai.dao.HighCompanyAccountMapper;
import com.hai.entity.*;
import com.hai.enum_type.CompanyAmountSourceTypeEnum;
import com.hai.enum_type.CompanyAmountTypeEnum;
import com.hai.model.UserInfoModel;
import com.hai.service.BsCompanyService;
import com.hai.service.BsOrganizationService;
import com.hai.service.HighCompanyAccountRecordService;
import com.hai.service.HighCompanyAccountService;
import org.apache.commons.collections4.MapUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Service("companyAccountService")
public class HighCompanyAccountServiceImpl implements HighCompanyAccountService {

    @Resource
    private BsCompanyService companyService;

    @Resource
    private HighCompanyAccountMapper companyAccountMapper;

    @Resource
    private HighCompanyAccountRecordService companyAccountRecordService;

    @Resource
    private BsOrganizationService organizationService;

    @Resource
    private RedisUtil redisUtil;

    @Resource
    private UserCenter userCenter;

    @Override
    public void editData(HighCompanyAccount companyAccount) {
        if (companyAccount.getId() == null) {
            companyAccount.setCreateTime(new Date());
            companyAccount.setUpdateTime(new Date());
            companyAccount.setStatus(1);
            companyAccountMapper.insert(companyAccount);
        } else {
            companyAccount.setUpdateTime(new Date());
            companyAccountMapper.updateByPrimaryKey(companyAccount);
        }
    }

    @Override
    @Transactional(rollbackFor=Exception.class,isolation = Isolation.SERIALIZABLE,propagation= Propagation.REQUIRES_NEW)
    public void recharge(Long orgId, BigDecimal amount, Map<String, Object> otherParam) {
        // 查询单位
        BsOrganization organization = organizationService.findById(orgId);
        if (organization == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的单位");
        }
        // 操作人
        UserInfoModel sessionModel = userCenter.getSessionModel(UserInfoModel.class);
        if (sessionModel == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知用户");
        }
        if (sessionModel.getBsCompany() == null || !(sessionModel.getBsCompany().getId().equals(organization.getCompanyId()))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "权限不足");
        }

        // 查询公司信息
        BsCompany company = companyService.getCompanyById(organization.getCompanyId());
        if (company == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知公司信息");
        }

        // 是否开通了账户
        HighCompanyAccount companyAccount = getAccountByOrgId(organization.getId());
        if (companyAccount == null) {
            companyAccount = new HighCompanyAccount();
            companyAccount.setCompanyId(organization.getCompanyId());
            companyAccount.setOrgId(organization.getId());
            companyAccount.setAmounts(new BigDecimal("0"));
            companyAccount.setAccountNo(BankNumberUtil.getBrankNumber("6"));
        }
        // 变更前金额
        BigDecimal beforeAmount = companyAccount.getAmounts();
        // 计算金额
        companyAccount.setAmounts(companyAccount.getAmounts().add(amount));
        // 变更后金额
        BigDecimal afterAmount = companyAccount.getAmounts();
        editData(companyAccount);

        HighCompanyAccountRecord record = new HighCompanyAccountRecord();
        record.setAfterAmount(companyAccount.getAmounts());
        record.setCompanyAmountId(companyAccount.getId());
        record.setCompanyName(company.getName());
        record.setCompanyId(organization.getCompanyId());
        record.setOrgId(organization.getId());
        record.setOrgName(organization.getName());
        record.setAmount(amount);
        record.setBeforeAmount(beforeAmount);
        record.setAfterAmount(afterAmount);
        record.setType(CompanyAmountTypeEnum.type1.getType());
        record.setSourceType(MapUtils.getInteger(otherParam, "sourceType"));
        record.setSourceId(MapUtils.getLong(otherParam, "sourceId"));
        record.setSourceContent(MapUtils.getString(otherParam, "sourceContent"));
        record.setOpUserId(sessionModel.getSecUser().getId());
        record.setOpUserName(sessionModel.getSecUser().getUserName());
        companyAccountRecordService.insertRecord(record);

        redisUtil.del("COMPANY_AMOUNT_RECHARGE_SMS_CODE");
    }

    @Override
    @Transactional(rollbackFor=Exception.class,isolation = Isolation.SERIALIZABLE,propagation= Propagation.REQUIRES_NEW)
    public void consume(Long orgId, BigDecimal amount, Map<String, Object> otherParam) {
        // 查询单位
        BsOrganization organization = organizationService.findById(orgId);
        if (organization == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知的单位");
        }
        // 操作人
        UserInfoModel sessionModel = userCenter.getSessionModel(UserInfoModel.class);
        if (sessionModel == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知用户");
        }
        if (sessionModel.getBsCompany() == null || !(sessionModel.getBsCompany().getId().equals(organization.getCompanyId()))) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "权限不足");
        }
        // 查询公司信息
        BsCompany company = companyService.getCompanyById(organization.getCompanyId());
        if (company == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "未知公司信息");
        }
        // 是否开通了账户
        HighCompanyAccount companyAccount = getAccountByOrgId(organization.getId());
        if (companyAccount == null) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "余额不足");
        }
        // 公司余额 是否小于 出账余额
        if (companyAccount.getAmounts().compareTo(amount) == -1) {
            throw ErrorHelp.genException(SysCode.System, ErrorCode.COMMON_ERROR, "余额不足");
        }
        // 变更前金额
        BigDecimal beforeAmount = companyAccount.getAmounts();
        // 计算金额
        companyAccount.setAmounts(companyAccount.getAmounts().subtract(amount));
        // 变更后金额
        BigDecimal afterAmount = companyAccount.getAmounts();
        editData(companyAccount);

        HighCompanyAccountRecord record = new HighCompanyAccountRecord();
        record.setAfterAmount(companyAccount.getAmounts());
        record.setCompanyAmountId(companyAccount.getId());
        record.setCompanyId(organization.getCompanyId());
        record.setCompanyName(organization.getName());
        record.setOrgId(organization.getId());
        record.setOrgName(organization.getName());
        record.setAmount(amount);
        record.setBeforeAmount(beforeAmount);
        record.setAfterAmount(afterAmount);
        record.setType(CompanyAmountTypeEnum.type2.getType());
        record.setSourceType(MapUtils.getInteger(otherParam, "sourceType"));
        record.setSourceId(MapUtils.getLong(otherParam, "sourceId"));
        record.setSourceContent(MapUtils.getString(otherParam, "sourceContent"));
        record.setOpUserId(sessionModel.getSecUser().getId());
        record.setOpUserName(sessionModel.getSecUser().getUserName());
        companyAccountRecordService.insertRecord(record);
    }

    @Override
    public HighCompanyAccount getAccountByOrgId(Long orgId) {
        HighCompanyAccountExample example = new HighCompanyAccountExample();
        example.createCriteria().andStatusEqualTo(1).andOrgIdEqualTo(orgId);
        List<HighCompanyAccount> list = companyAccountMapper.selectByExample(example);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
}
