package pwc.taxtech.atms.service.impl;

import com.google.common.collect.Lists;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import pwc.taxtech.atms.common.CommonUtils;
import pwc.taxtech.atms.exception.ServiceException;
import pwc.taxtech.atms.constant.ActiveStatus;
import pwc.taxtech.atms.constant.StandAccountConstant;
import pwc.taxtech.atms.constant.enums.StdAccountEnum;
import pwc.taxtech.atms.dao.OrganizationMapper;
import pwc.taxtech.atms.dao.StandardAccountMapper;
import pwc.taxtech.atms.dao.StandardAccountDao;
import pwc.taxtech.atms.dto.stdaccount.StandardAccountDto;
import pwc.taxtech.atms.dto.stdaccount.StdAccountFancyTreeDto;
import pwc.taxtech.atms.entity.Organization;
import pwc.taxtech.atms.entity.StandardAccount;
import pwc.taxtech.atms.entity.StandardAccountExample;
import pwc.taxtech.atms.service.StdAccountService;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
public class StdAccountServiceImpl extends BaseService implements StdAccountService {

    @Autowired
    private StandardAccountMapper standardAccountMapper;

    @Autowired
    private OrganizationMapper organizationMapper;
    @Autowired
    private StandardAccountDao standardAccountDao;

    @Override
    public List<StdAccountFancyTreeDto> getStdAccountHierarchy(String orgId) throws ServiceException {
        List<StdAccountFancyTreeDto> resultList;
        try {
            if (StringUtils.isBlank(orgId)) {
                return Collections.emptyList();
            }
            Organization organization = organizationMapper.selectByPrimaryKey(orgId);
            if (null == organization) {
                return Collections.emptyList();
            }
            String industryId = organization.getIndustryId();
            resultList = new ArrayList<>();
            if (StringUtils.isNotBlank(industryId)) {
                List<StdAccountFancyTreeDto> dtoList = Lists.newArrayList();
                StandardAccountExample example = new StandardAccountExample();
                StandardAccountExample.Criteria criteria = example.createCriteria();
                criteria.andIndustryIdEqualTo(industryId).andRuleTypeEqualTo(2).andIsActiveEqualTo(true);
                List<StandardAccount> standardAccountList = standardAccountMapper.selectByExample(example);
                List<StandardAccount> topList = standardAccountList.stream().filter(x -> StringUtils.isBlank(x.getParentCode()))
                        .collect(Collectors.toList());
                for (StandardAccount topNode : topList) {
                    StdAccountFancyTreeDto dto = rotateToDto(topNode);
                    getSubStdAccount(dto, standardAccountList);
                    dtoList.add(dto);
                }
                Map<String, List<StdAccountFancyTreeDto>> map = dtoList.stream().collect(Collectors.groupingBy(x -> x.getAcctProp()));
                for (Map.Entry<String, List<StdAccountFancyTreeDto>> entry : map.entrySet()) {
                    StdAccountFancyTreeDto root = new StdAccountFancyTreeDto();
                    root.setExpanded(false);
                    root.setHasChildren(CollectionUtils.isNotEmpty(entry.getValue()));
                    root.setTitle(StdAccountEnum.AcctProp.MAPPING.get(entry.getKey()));
                    root.setChildren(entry.getValue());
                    resultList.add(root);
                }
            }
        } catch (Exception e) {
            throw new ServiceException("getStdAccountHierarchy error.", e);
        }
        return resultList;
    }

    @Override
    public List<StandardAccountDto> GetStdAccountLinkEtsAccount(String orgId, String accountSetId) {
        if (StringUtils.isBlank(orgId)) {
            return Collections.emptyList();
        }
        //todo
        Organization organization = organizationMapper.selectByPrimaryKey(orgId);
        if (organization == null) {
            return Collections.emptyList();
        }
        String industryId = organization.getIndustryId();

        List<StandardAccount> stdAccounts = standardAccountDao.getStdAccount(StdAccountEnum.RuleType.TWO, industryId, true, true);

        if (CollectionUtils.isEmpty(stdAccounts)) {
            stdAccounts = standardAccountDao.getStdAccount(StdAccountEnum.RuleType.TWO, "0", true, true);
        }


        return Collections.emptyList();
    }

    @Override
    public List<StandardAccountDto> getStdAccountByIndustry(String industryId) {
        StandardAccountExample example = new StandardAccountExample();
        example.createCriteria().andRuleTypeEqualTo((int)StandAccountConstant.TWO).andIsActiveEqualTo(ActiveStatus.Active).andIndustryIdEqualTo(industryId);

        example.setOrderByClause("Code");

        List<StandardAccount> items = standardAccountMapper.selectByExample(example);
        List<StandardAccountDto> dtos = new ArrayList<>();

        for (StandardAccount item : items) {
            StandardAccountDto dto = new StandardAccountDto();
            CommonUtils.copyProperties(item, dto);
            dto.setTitle(item.getCode() + "-" + (item.getDirection().equals(1) ? "借" : "贷") + "-" + item.getName());
            dtos.add(dto);
        }
        return dtos;
    }

    private void getSubStdAccount(StdAccountFancyTreeDto node, List<StandardAccount> allList) {
        List<StdAccountFancyTreeDto> childList = allList.stream().filter(x -> StringUtils.equals(node.getCode(), x.getParentCode()))
                .map(this::rotateToDto).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(childList)) {
            node.setChildren(childList);
            node.setHasChildren(true);
            for (StdAccountFancyTreeDto tmp : childList) {
                getSubStdAccount(tmp, allList);
            }
        }
    }

    private StdAccountFancyTreeDto rotateToDto(StandardAccount account) {
        StdAccountFancyTreeDto dto = new StdAccountFancyTreeDto();
        dto.setExpanded(false);
        dto.setHasChildren(false);
        CommonUtils.copyProperties(account, dto);
        dto.setTitle(dto.getCode() + "-" + (StringUtils.equals(dto.getDirection(), "1") ? "借" : "贷") + "-" + dto.getName());
        return dto;
    }
}