package com.crm.manager.service.impl;

import com.crm.manager.dao.mapper.RiskLeverageGroupMapper;
import com.crm.manager.dao.repository.RiskLeverageGroupRepository;
import com.crm.manager.service.RiskLeverageGroupRuleService;
import com.crm.manager.service.RiskLeverageGroupService;
import com.crm.manager.service.risk.RiskLeverageGroupExcludeLoginService;
import com.crm.rely.backend.core.constant.Constants;
import com.crm.rely.backend.core.constant.ManagerConstant;
import com.crm.rely.backend.core.dto.base.PageDto;
import com.crm.rely.backend.core.dto.base.ResultWithPagerDto;
import com.crm.rely.backend.core.dto.risk.leverage.group.RiskLeverageGroupDto;
import com.crm.rely.backend.core.dto.risk.leverage.group.rule.RiskLeverageGroupRuleDto;
import com.crm.rely.backend.core.entity.base.SingleLongEntity;
import com.crm.rely.backend.core.entity.risk.leverage.group.RiskLeverageGroupAddEntity;
import com.crm.rely.backend.core.entity.risk.leverage.group.RiskLeverageGroupDeleteEntity;
import com.crm.rely.backend.core.entity.risk.leverage.group.RiskLeverageGroupSearchPageEntity;
import com.crm.rely.backend.core.entity.risk.leverage.group.RiskLeverageGroupUpdateEntity;
import com.crm.rely.backend.core.pojo.table.RiskLeverageGroupTable;
import com.crm.rely.backend.exception.ServiceException;
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.util.ArrayList;
import java.util.List;

@Service
public class RiskLeverageGroupServiceImpl implements RiskLeverageGroupService {

    @Autowired
    private RiskLeverageGroupRepository riskLeverageGroupRepository;

    @Autowired
    private RiskLeverageGroupMapper riskLeverageGroupMapper;

    @Autowired
    private RiskLeverageGroupExcludeLoginService riskLeverageGroupExcludeLoginService;

    @Autowired
    private RiskLeverageGroupRuleService riskLeverageGroupRuleService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(RiskLeverageGroupAddEntity entity) throws ServiceException {
        existsByGroupCode(entity.getGroupCode());

        RiskLeverageGroupTable riskLeverageGroupTable = new RiskLeverageGroupTable();
        BeanUtils.copyProperties(entity, riskLeverageGroupTable);

        riskLeverageGroupRepository.save(riskLeverageGroupTable);

        riskLeverageGroupExcludeLoginService.save(riskLeverageGroupTable.getId(), entity.getExcludeLoginSaveEntities());

        riskLeverageGroupRuleService.save(riskLeverageGroupTable.getId(), entity.getRules());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(RiskLeverageGroupUpdateEntity entity) throws ServiceException {
        RiskLeverageGroupTable riskLeverageGroupTable = riskLeverageGroupRepository.findFirstById(entity.getId());
        if (riskLeverageGroupTable == null) {
            throw ServiceException.notFoundException();
        }

        if (!entity.getGroupCode().equals(riskLeverageGroupTable.getGroupCode())) {
            existsByGroupCode(entity.getGroupCode());
        }

        BeanUtils.copyProperties(entity, riskLeverageGroupTable);

        riskLeverageGroupRepository.save(riskLeverageGroupTable);

        riskLeverageGroupExcludeLoginService.save(riskLeverageGroupTable.getId(), entity.getExcludeLoginSaveEntities());

        riskLeverageGroupRuleService.save(riskLeverageGroupTable.getId(), entity.getRules());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void delete(RiskLeverageGroupDeleteEntity entity) throws ServiceException {

        List<RiskLeverageGroupTable> riskLeverageGroupTables = riskLeverageGroupRepository.findAllByIdIn(entity.getIds());
        if (riskLeverageGroupTables == null || riskLeverageGroupTables.size() <= 0) {
            return;
        }
        riskLeverageGroupRepository.delete(riskLeverageGroupTables);

        riskLeverageGroupExcludeLoginService.delete(entity.getIds());

        riskLeverageGroupRuleService.delete(entity.getIds());
    }

    @Override
    public ResultWithPagerDto<RiskLeverageGroupDto> searchPageList(RiskLeverageGroupSearchPageEntity entity) throws ServiceException {
        Integer count = riskLeverageGroupMapper.countList(entity);
        PageDto pageDto = PageDto.format(entity, count);
        if (count == null || count <= 0) {
            return ResultWithPagerDto.success(pageDto);
        }

        List<RiskLeverageGroupDto> riskRevokeCreditRuleGroupDto = getRiskLeverageGroupDto(entity);
        if (riskRevokeCreditRuleGroupDto == null) {
            throw ServiceException.exception(Constants.SYSTEM_ERROR);
        }
        return ResultWithPagerDto.success(pageDto, riskRevokeCreditRuleGroupDto);
    }

    @Override
    public RiskLeverageGroupDto searchSingle(SingleLongEntity entity) throws ServiceException {
        RiskLeverageGroupTable riskLeverageGroupTable = riskLeverageGroupRepository.getFirstById(entity.getId());

        RiskLeverageGroupDto riskLeverageGroupDto = transform(riskLeverageGroupTable);

        List<Long> excludeLogins = riskLeverageGroupExcludeLoginService.getExcludeLoginDto(riskLeverageGroupDto.getId());
        riskLeverageGroupDto.setExcludeLogins(excludeLogins);

        List<RiskLeverageGroupRuleDto> rules = riskLeverageGroupRuleService.getRuleDto(riskLeverageGroupDto.getId());
        riskLeverageGroupDto.setRules(rules);

        return riskLeverageGroupDto;
    }

    private void existsByGroupCode(String groupCode) throws ServiceException {
        boolean exist = riskLeverageGroupRepository.existsByGroupCode(groupCode);

        if (exist) {
            throw ServiceException.exception(ManagerConstant.CUSTOM_GROUP_CODE_IS_EXIST);
        }
    }

    private List<RiskLeverageGroupDto> getRiskLeverageGroupDto(RiskLeverageGroupSearchPageEntity entity) throws ServiceException {
        List<RiskLeverageGroupTable> riskRevokeCreditRuleGroupTables = riskLeverageGroupMapper.pageList(entity);

        if (riskRevokeCreditRuleGroupTables == null || riskRevokeCreditRuleGroupTables.size() <= 0) {

            return null;
        }
        List<RiskLeverageGroupDto> riskRevokeCreditRuleGroupDtos = new ArrayList<>(riskRevokeCreditRuleGroupTables.size());

        for (RiskLeverageGroupTable riskRevokeCreditRuleGroupTable : riskRevokeCreditRuleGroupTables) {
            RiskLeverageGroupDto riskRevokeCreditRuleGroupDto = transform(riskRevokeCreditRuleGroupTable);
            riskRevokeCreditRuleGroupDtos.add(riskRevokeCreditRuleGroupDto);
        }
        return riskRevokeCreditRuleGroupDtos;
    }

    private RiskLeverageGroupDto transform(RiskLeverageGroupTable riskRevokeCreditRuleGroupTable) {
        RiskLeverageGroupDto riskRevokeCreditRuleGroupDto = new RiskLeverageGroupDto();
        BeanUtils.copyProperties(riskRevokeCreditRuleGroupTable, riskRevokeCreditRuleGroupDto);
        return riskRevokeCreditRuleGroupDto;
    }
}
