package cn.com.ty.lift.business.contract.service;

import cn.com.ty.lift.business.contract.dao.entity.Contracts;
import cn.com.ty.lift.business.contract.dao.entity.ContractsHistory;
import cn.com.ty.lift.business.contract.dao.entity.Payment;
import cn.com.ty.lift.business.contract.dao.entity.model.request.ContractRequest;
import cn.com.ty.lift.business.contract.dao.entity.model.response.ContractResponse;
import cn.com.ty.lift.business.contract.dao.mapper.ContractsMapper;
import cn.com.ty.lift.business.framework.util.MessageUtils;
import cn.com.ty.lift.business.project.dao.entity.Project;
import cn.com.ty.lift.business.project.service.ProjectService;
import cn.com.ty.lift.common.utils.DateUtils;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

import static java.math.BigDecimal.ZERO;

/**
 * @author bieao
 * @date 2019/12/07
 * @description 合同管理业务层
 */
@Service
@Slf4j
public class ContractService extends ServiceImpl<ContractsMapper, Contracts> {

    @Resource
    private ContractsMapper contractsMapper;

    @Resource
    private ContractHistoryService contractHistoryService;

    @Resource
    private PaymentService paymentService;

    @Resource
    private ProjectService projectService;

    /**
     * @param request 合同列表查询条件
     * @return RestResponse 合同分页列表结果
     * @description 查询合同列表
     * @date 2019/12/7 11:53 AM
     */
    public IPage<ContractResponse> list(ContractRequest request) {
        request.addDesc("c.end_date");
        return contractsMapper.findByCondition(request.getPage(), request);
    }

    /**
     * @param request 新增合同数据项
     * @return 1.成功, 0.失败, 消息描述
     * @description 新增合同
     * @date 2019/12/7 3:31 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse add(ContractRequest request) {
        Contracts contracts = request.getContracts();
        Long projectId = request.getProjectId();
        if (Objects.isNull(projectId)) {
            //插入项目信息
            Project project = new Project();
            project.setProjectName(request.getProjectName());
            project.setAddress(request.getProjectAddress());
            project.setNum(contracts.getLiftNum());
            project.setStartDate(contracts.getStarDate());
            project.setEndDate(contracts.getEndDate());
            project.setMtCompanyId(contracts.getMtCompanyId());
            boolean pro = projectService.saveProject(project);
            if (!pro) return RestResponse.fail(MessageUtils.get("msg.add.fail"));
            contracts.setProjectId(project.getId());
        } else {
            contracts.setProjectId(projectId);
        }
        if (ObjectUtil.isEmpty(contracts.getCode())) {
            //按当前日期时间戳自动生成合同编号
            String contractCode = DateUtils.generateCode();
            contracts.setCode("HT" + contractCode);
        }
        List<Payment> paymentList = request.getPaymentList();
        if (CollUtil.isNotEmpty(paymentList)) {
            //应收金额总计
            BigDecimal planMoneyTotal = paymentList.stream().map(Payment::getPlanMoney).reduce(ZERO, BigDecimal::add);
            contracts.setPlanMoneyTotal(planMoneyTotal);
            //实收金额总计
            BigDecimal workMoneyTotal = paymentList.stream().map(Payment::getWorkMoney).reduce(ZERO, BigDecimal::add);
            contracts.setWorkMoneyTotal(workMoneyTotal);
            //开票金额总计
            BigDecimal invoiceTotal = paymentList.stream().map(Payment::getAmountInvoice).reduce(ZERO, BigDecimal::add);
            contracts.setInvoiceMoneyTotal(invoiceTotal);
        }
        //插入合同信息
        boolean result = save(contracts);
        if (!result) {
            //强制手动事务回滚
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.add.fail"));
        }
        //批量插入收款信息
        boolean ret = paymentService.insertBatch(paymentList, contracts);
        if (!ret) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.add.batch.fail"));
        }
        return RestResponse.success(null, MessageUtils.get("msg.add.success"));
    }

   /**
    * @param request 续签合同数据项
    * @return 1.成功, 0.失败, 消息描述
    * @description 续签合同
    * @date 2020/5/3 10:48 上午
    */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse renew(ContractRequest request) {
        Contracts contracts = request.getContracts();
        //查询原有合同是否存在
        Long contractId = request.getContractId();
        Contracts oldContract = getOne(contractId);
        if (Objects.isNull(oldContract))
            return RestResponse.fail(MessageUtils.get("msg.contract.not.exist"));
        if (ObjectUtil.isEmpty(contracts.getCode())) {
            //按当前日期时间戳自动生成合同编号
            String contractCode = DateUtils.generateCode();
            contracts.setCode("HT" + contractCode);
        }
        contracts.setProjectId(request.getProjectId());
        List<Payment> paymentList = request.getPaymentList();
        if (CollUtil.isNotEmpty(paymentList)) {
            //应收金额总计
            BigDecimal planMoneyTotal = paymentList.stream().map(Payment::getPlanMoney).reduce(ZERO, BigDecimal::add);
            contracts.setPlanMoneyTotal(planMoneyTotal);
            //实收金额总计
            BigDecimal workMoneyTotal = paymentList.stream().map(Payment::getWorkMoney).reduce(ZERO, BigDecimal::add);
            contracts.setWorkMoneyTotal(workMoneyTotal);
            //开票金额总计
            BigDecimal invoiceTotal = paymentList.stream().map(Payment::getAmountInvoice).reduce(ZERO, BigDecimal::add);
            contracts.setInvoiceMoneyTotal(invoiceTotal);
        }
        //插入新合同信息
        boolean result = save(contracts);
        if (!result)
            return RestResponse.fail(MessageUtils.get("msg.add.fail"));

        //修改原有合同
        oldContract.setNextId(contracts.getId());
        boolean ret = updateById(oldContract);
        if (!ret) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return RestResponse.fail(MessageUtils.get("msg.add.fail"));
        }
        //查询原有付款列表
        List<Payment> oldPaymentList = paymentService.paymentList(contractId);
        paymentList.forEach(entry -> {
            entry.setContractsId(contracts.getId());
            entry.setCode("PA" + DateUtils.generateCode());
            entry.setType(contracts.getType());
        });
        //修改或删除付款列表
        return paymentService.modifyPayment(oldPaymentList, paymentList);
    }

    /**
     * @param request 合同复核
     * @return 1.成功, 0.失败, 消息描述
     * @description 合同复核
     * @date 2020/2/11 12:55 下午
     */
    public RestResponse check(ContractRequest request) {
        Contracts contracts = getOne(request.getId());
        if (Objects.isNull(contracts))
            return RestResponse.fail(MessageUtils.get("msg.contract.not.exist"));
        contracts.setIsCheck(1);
        boolean result = updateById(contracts);
        if (!result)
            return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
        return RestResponse.success(MessageUtils.get("msg.modify.success"));
    }

    /**
     * @param id 合同id
     * @return 合同
     * @description 查询合同
     * @date 2019/12/20 11:04 AM
     */
    public Contracts getOne(Long id) {
        QueryWrapper<Contracts> queryWrapper = new QueryWrapper<>();
        LambdaQueryWrapper<Contracts> lambdaQueryWrapper = queryWrapper.lambda();
        lambdaQueryWrapper.eq(Contracts::getId, id);
        return getOne(lambdaQueryWrapper);
    }

    /**
     * @param request 修改合同、项目、付款信息数据项
     * @return 1.成功, 0.失败, 消息描述
     * @description 合同变更
     * @date 2019/12/7 3:31 PM
     */
    @Transactional(rollbackFor = Exception.class)
    public RestResponse modify(ContractRequest request) {
        Contracts contracts = request.getContracts();
        Long contractId = contracts.getId();
        Contracts oldContract = getOne(contractId);
        if (Objects.isNull(oldContract))
            return RestResponse.fail(MessageUtils.get("msg.contract.not.exist"));
        //修改合同信息
        contracts.setIsCheck(0);
        List<Payment> paymentList = request.getPaymentList();
        //应收金额总计
        BigDecimal planMoneyTotal = paymentList.stream().map(Payment::getPlanMoney).reduce(ZERO, BigDecimal::add);
        contracts.setPlanMoneyTotal(planMoneyTotal);
        //实收金额总计
        BigDecimal workMoneyTotal = paymentList.stream().map(Payment::getWorkMoney).reduce(ZERO, BigDecimal::add);
        contracts.setWorkMoneyTotal(workMoneyTotal);
        //开票金额总计
        BigDecimal invoiceTotal = paymentList.stream().map(Payment::getAmountInvoice).reduce(ZERO, BigDecimal::add);
        contracts.setInvoiceMoneyTotal(invoiceTotal);

        boolean contractResult = updateById(contracts);
        if (!contractResult)
            return RestResponse.fail(MessageUtils.get("msg.modify.fail"));

        //生成合同操作记录
        ContractsHistory history = contractHistoryService.createOperaHistory(oldContract, contracts);
        if (Objects.nonNull(history)) {
            //保存合同操作记录
            boolean historyResult = contractHistoryService.save(history);
            if (!historyResult) {
                TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
                return RestResponse.fail(MessageUtils.get("msg.modify.fail"));
            }
        }
        //查询原有付款列表
        List<Payment> oldPaymentList = paymentService.paymentList(contractId);
        //设置合同付款的合同id
        paymentList.forEach(entry -> {
            entry.setContractsId(contracts.getId());
            entry.setCode("PA" + DateUtils.generateCode());
            entry.setType(contracts.getType());
        });
        //修改或删除付款列表
        return paymentService.modifyPayment(oldPaymentList, paymentList);
    }

    /**
     * @param id 主键id
     * @return Contracts 合同详情
     * @description 查看合同详情
     * @date 2019/12/7 11:50 AM
     */
    public Map<String, Object> detail(Long id) {
        QueryWrapper<Contracts> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id", id);
        Contracts contracts = getOne(queryWrapper);
        List<Payment> paymentMap = paymentService.paymentList(id);
        Map<String, Object> resultMap = new HashMap<>();
        resultMap.put("contract", contracts);
        resultMap.put("paymentList", paymentMap);
        Optional<Project> project = projectService.getOne(contracts.getProjectId());
        project.ifPresent(entry -> resultMap.put("project", project.get()));
        return resultMap;
    }
}
