package com.fjhx.service.contract.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fjhx.base.BaseEntity;
import com.fjhx.base.Condition;
import com.fjhx.entity.contract.Contract;
import com.fjhx.entity.contract.ContractDetails;
import com.fjhx.mapper.contract.ContractMapper;
import com.fjhx.params.contract.ContractVo;
import com.fjhx.service.contract.ContractDetailsService;
import com.fjhx.service.contract.ContractService;
import org.springblade.core.secure.utils.AuthUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 合同 服务实现类
 * </p>
 *
 * @author ${author}
 * @since 2022-10-25
 */
@Service
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract> implements ContractService {

    @Autowired
    private ContractDetailsService contractDetailsService;

    @Override
    public Page<Contract> getPage(Condition condition) {
        String keyword = condition.getKeyword();

        return lambdaQuery()
                .and(ObjectUtil.isNotEmpty(keyword), q -> q
                        .like(Contract::getCode, keyword)
                        .like(Contract::getLinkName, keyword)
                )
                .eq(BaseEntity::getTenantId, AuthUtil.getTenantId())
                .orderByDesc(BaseEntity::getId)
                .page(condition.getPage());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void add(ContractVo contractVo) {
        synchronized (this) {
            contractVo.setCode(getCode());
            save(contractVo);
        }

        List<ContractDetails> contractDetailsList = contractVo.getContractDetailsList();
        contractDetailsList.forEach(item -> item.setContractId(contractVo.getId()));
        contractDetailsService.saveBatch(contractDetailsList);

    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void edit(ContractVo contractVo) {
        updateById(contractVo);

        List<ContractDetails> contractDetailsList = contractVo.getContractDetailsList();
        contractDetailsList.forEach(item -> item.setContractId(contractVo.getId()));
        contractDetailsService.saveOrUpdateBatch(contractDetailsList);

        List<Long> customerLinkIdList = contractDetailsList.stream().map(BaseEntity::getId).collect(Collectors.toList());
        contractDetailsService.remove(Wrappers.<ContractDetails>lambdaQuery()
                .eq(ContractDetails::getContractId, contractVo.getId())
                .notIn(BaseEntity::getId, customerLinkIdList));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void delete(ContractVo contractVo) {
        removeById(contractVo.getId());
        contractDetailsService.remove(ContractDetails::getContractId, contractVo.getId());
    }

    @Override
    public ContractVo details(Long id) {
        Contract contract = getById(id);
        ContractVo contractVo = BeanUtil.toBean(contract, ContractVo.class);

        List<ContractDetails> list = contractDetailsService.list(ContractDetails::getContractId, id);
        contractVo.setContractDetailsList(list);

        return contractVo;
    }

    private String getCode() {
        Contract contract = getOne(Wrappers.<Contract>lambdaQuery()
                .eq(BaseEntity::getTenantId, AuthUtil.getTenantId())
                .select(Contract::getCode)
                .orderByDesc(Contract::getCode)
                .last("limit 1")
        );

        if (contract == null) {
            return "SC00001";
        }
        String code = contract.getCode();
        int num = Convert.toInt(code.replace("SC", "")) + 1;
        if (num < 10) {
            return "SC0000" + num;
        }
        if (num < 100) {
            return "SC000" + num;
        }
        if (num < 1000) {
            return "SC00" + num;
        }
        if (num < 10000) {
            return "SC0" + num;
        }

        return "SC" + num;
    }

}
