package com.liquidnet.service.adam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.liquidnet.service.adam.constant.AdamAccountConstants;
import com.liquidnet.service.adam.constant.AdamAdminisConstants;
import com.liquidnet.service.adam.dto.AdamAccountWalletParam;
import com.liquidnet.service.adam.dto.AdamAdminisWalletParam;
import com.liquidnet.service.adam.dto.base.AdamCurrentUser;
import com.liquidnet.service.adam.entity.AdamAccountWallet;
import com.liquidnet.service.adam.entity.AdamWalletAccess;
import com.liquidnet.service.adam.mapper.AdamWalletAccessMapper;
import com.liquidnet.service.adam.service.IAdamAccountWalletService;
import com.liquidnet.service.adam.service.IAdamAdminisProcessHisService;
import com.liquidnet.service.adam.service.IAdamComProfileService;
import com.liquidnet.service.adam.service.IAdamWalletAccessService;
import com.liquidnet.service.adam.vo.AdamUserVo;
import com.liquidnet.service.adam.vo.AdamWalletAccessVo;
import com.liquidnet.service.adam.vo.AdamAdminisWalletVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.util.CollectionUtils;

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

@Slf4j
@Service
public class AdamWalletAccessServiceImpl extends ServiceImpl<AdamWalletAccessMapper, AdamWalletAccess> implements IAdamWalletAccessService {
    @Autowired
    private AdamWalletAccessMapper adamWalletAccessMapper;
    @Autowired
    private IAdamAccountWalletService adamAccountWalletService;
    @Autowired
    private IAdamComProfileService adamComProfileService;
    @Autowired
    private IAdamAdminisProcessHisService adamAdminisProcessHisService;

    //    @Override
    public int removeByUserId(String userId) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("user_id", userId);
        return adamWalletAccessMapper.deleteByMap(map);
    }

    public int removeByComId(String comId) {
        Map<String, Object> map = Maps.newHashMap();
        map.put("com_id", comId);
        return adamWalletAccessMapper.deleteByMap(map);
    }

    @Override
    public List<AdamWalletAccess> queryByUserId(String userId) {
        LambdaQueryWrapper<AdamWalletAccess> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AdamWalletAccess::getUserId, userId);
        return adamWalletAccessMapper.selectList(queryWrapper);
    }

    @Override
    public List<AdamAdminisWalletVo> queryForUserProfileAdminis(String comId, String userId) {
        AdamAccountWalletParam accountWalletParam = new AdamAccountWalletParam();
        accountWalletParam.setComId(comId);
        accountWalletParam.setState(AdamAccountConstants.StateEnum.S2.getCode());
        List<AdamAccountWallet> accountWalletList = adamAccountWalletService.selectList(accountWalletParam);

        List<AdamWalletAccess> walletAccessList = this.queryByUserId(userId);
        List<String> walletNoAccessList = walletAccessList.stream().map(AdamWalletAccess::getFinWalletNo).collect(Collectors.toList());

        List<AdamAdminisWalletVo> walletVoList = Lists.newLinkedList();
        accountWalletList.forEach(r -> {
            AdamAdminisWalletVo copy = AdamAdminisWalletVo.getNew().copy(r);
            copy.setAccessExecutor(walletNoAccessList.contains(r.getFinWalletNo()) ? "1" : "2");
            walletVoList.add(copy);
        });
        return walletVoList;
    }

    @Override
    public List<AdamWalletAccessVo> queryForWalletPermission(String comId) {
        AdamAccountWalletParam accountWalletParam = new AdamAccountWalletParam();
        accountWalletParam.setComId(comId);
        accountWalletParam.setState(AdamAccountConstants.StateEnum.S2.getCode());
        List<AdamAccountWallet> accountWalletList = adamAccountWalletService.selectList(accountWalletParam);

        Map<String, List<AdamUserVo>> walletAccessWithUserMap = this.queryWithUserGroupByWalletNo(comId);

        List<AdamWalletAccessVo> walletAccessVoList = Lists.newLinkedList();
        accountWalletList.forEach(r -> {
            AdamWalletAccessVo vo = AdamWalletAccessVo.getNew().copy(r);
            vo.setAllowedUserList(walletAccessWithUserMap.get(r.getFinWalletNo()));
            walletAccessVoList.add(vo);
        });
        return walletAccessVoList;
    }

    @Override
    public boolean saveWalletAccess(List<String> allowedWalletList, String comId, String userId) {
        this.removeByUserId(userId);

        List<AdamWalletAccess> assignList = Lists.newArrayList();

        allowedWalletList.forEach(r -> {
            AdamWalletAccess newObj = AdamWalletAccess.getNew();
            newObj.setUserId(userId);
            newObj.setComId(comId);
            newObj.setFinWalletNo(r);
            assignList.add(newObj);
        });

        return this.saveBatch(assignList);
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public boolean saveUserAccessWithSpecialSetting(AdamAdminisWalletParam parameter, AdamCurrentUser currentUser) {
        String comId = currentUser.getComId();
        this.removeByComId(comId);

        Map<String, List<String>> walletAccessListMap = parameter.getWalletAccessListMap();

        List<AdamWalletAccess> assignList = Lists.newArrayList();

        walletAccessListMap.forEach((k, v) -> {
            v.forEach(r -> {
                AdamWalletAccess newObj = AdamWalletAccess.getNew();
                newObj.setUserId(r);
                newObj.setFinWalletNo(k);
                newObj.setComId(comId);
                assignList.add(newObj);
            });
        });

        boolean a = this.saveBatch(assignList);

        int i = adamComProfileService.updateByItem(comId, "newWalletAssignToAllUser", parameter.getNewWalletAssignToAllUser());

        if (!a || i != 1) {
            TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
            return false;
        }
        return true;
    }

    private Map<String, List<AdamUserVo>> queryWithUserGroupByWalletNo(String comId) {
        List<Map<String, String>> walletAccessWithUserList = adamWalletAccessMapper.selectAllByComIdWithUser(comId);

        Map<String, List<AdamUserVo>> walletAccessWithUserMap = Maps.newHashMap();
        walletAccessWithUserList.forEach(r -> {
            String walletNo = r.get("walletNo");

            List<AdamUserVo> existMap = walletAccessWithUserMap.get(walletNo);

            AdamUserVo newObj = AdamUserVo.getNew();
            newObj.setUserId(r.get("userId"));
            newObj.setFirstName(r.get("firstName"));
            newObj.setLastName(r.get("lastName"));
            newObj.setCompanyEmail(r.get("companyEmail"));

            if (CollectionUtils.isEmpty(existMap)) {
                walletAccessWithUserMap.put(walletNo, Lists.newArrayList(newObj));
            } else {
                existMap.add(newObj);
            }
        });
        return walletAccessWithUserMap;
    }
}
