package com.sf.service.gateway.service.impl;

import java.util.*;
import java.util.stream.Collectors;

import cn.hutool.core.collection.CollUtil;
import com.sf.common.utils.*;
import com.sf.service.gateway.domain.GatewayInterfaceInfo;
import com.sf.service.gateway.domain.GatewayInterfaceLinkStrategy;
import com.sf.service.gateway.domain.GatewayStrategy;
import com.sf.service.gateway.domain.dto.InsertGatewayInterfaceInfoDTO;
import com.sf.service.gateway.domain.dto.UpdateGatewayInterfaceInfoDTO;
import com.sf.service.gateway.enums.GatewayDataStatus;
import com.sf.service.gateway.enums.GatewayStrategyType;
import com.sf.service.gateway.mapper.GatewayInterfaceInfoMapper;
import com.sf.service.gateway.mapper.GatewayInterfaceLinkStrategyMapper;
import com.sf.service.gateway.service.IGatewayInterfaceInfoService;
import com.sf.service.gateway.service.IGatewayStrategyService;
import com.sf.service.index.util.AppUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;

/**
 * 接口管理Service业务层处理
 *
 * @author zoukun
 * @date 2024-04-22
 */
@Slf4j
@Service
public class GatewayInterfaceInfoServiceImpl implements IGatewayInterfaceInfoService {

    @Autowired
    private GatewayInterfaceInfoMapper gatewayInterfaceInfoMapper;

    @Autowired
    private GatewayInterfaceLinkStrategyMapper gatewayInterfaceLinkStrategyMapper;

    @Autowired
    private IGatewayStrategyService gatewayStrategyService;

    /**
     * 查询接口管理
     *
     * @param id 接口管理主键
     * @return 接口管理
     */
    @Override
    public GatewayInterfaceInfo selectGatewayInterfaceInfoById(Long id) {
        return gatewayInterfaceInfoMapper.selectGatewayInterfaceInfoById(id);
    }

    /**
     * 查询接口管理列表
     *
     * @param gatewayInterfaceInfo 接口管理
     * @return 接口管理
     */
    @Override
    public List<GatewayInterfaceInfo> selectGatewayInterfaceInfoList(GatewayInterfaceInfo gatewayInterfaceInfo) {
        return gatewayInterfaceInfoMapper.selectGatewayInterfaceInfoList(gatewayInterfaceInfo);
    }

    /**
     * 新增接口管理
     *
     * @param gatewayInterfaceInfo 接口管理
     * @return 结果
     */
    @Override
    public Long insertGatewayInterfaceInfo(GatewayInterfaceInfo gatewayInterfaceInfo) {
        gatewayInterfaceInfo.setAppCode(AppUtils.getAppCodeFromRequestHeader());
        String username = SecurityUtils.getUsername();
        gatewayInterfaceInfo.setCreated(username);
        gatewayInterfaceInfo.setModified(username);
        Date nowDate = DateUtils.getNowDate();
        gatewayInterfaceInfo.setCreateTime(nowDate);
        gatewayInterfaceInfo.setUpdateTime(nowDate);
        Assert.hasText(gatewayInterfaceInfo.getInterfacePath(),"接口路径不能为空");
        gatewayInterfaceInfo.setUriRegular(RegexUtils.isRegex(gatewayInterfaceInfo.getInterfacePath()));
        try {
            gatewayInterfaceInfoMapper.insertGatewayInterfaceInfo(gatewayInterfaceInfo);
            return gatewayInterfaceInfo.getId();
        }catch (DuplicateKeyException e){
            throw new IllegalArgumentException("接口名称不可重复!");
        }

    }

    /**
     * 修改接口管理
     *
     * @param gatewayInterfaceInfo 接口管理
     * @return 结果
     */
    @Override
    public int updateGatewayInterfaceInfo(GatewayInterfaceInfo gatewayInterfaceInfo) {
        gatewayInterfaceInfo.setModified(SecurityUtils.getUsername());
        gatewayInterfaceInfo.setUpdateTime(DateUtils.getNowDate());
        String interfacePath = gatewayInterfaceInfo.getInterfacePath();
        Assert.hasText(interfacePath,"接口路径不能为空");
        gatewayInterfaceInfo.setUriRegular(RegexUtils.isRegex(interfacePath));
        try {
            return gatewayInterfaceInfoMapper.updateGatewayInterfaceInfo(gatewayInterfaceInfo);
        }catch (DuplicateKeyException e){
            throw new IllegalArgumentException("接口名称不可重复!");
        }
    }

    /**
     * 批量删除接口管理
     *
     * @param ids 需要删除的接口管理主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteGatewayInterfaceInfoByIds(Long[] ids) {
        if (ids == null || ids.length == 0) {
            return 0;
        }
        gatewayInterfaceLinkStrategyMapper.deleteByInterfaceIds(CollUtil.newHashSet(ids));
        return gatewayInterfaceInfoMapper.deleteGatewayInterfaceInfoByIds(ids);
    }

    /**
     * 删除接口管理信息
     *
     * @param id 接口管理主键
     * @return 结果
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteGatewayInterfaceInfoById(Long id) {
        if (id == null) {
            return 0;
        }
        gatewayInterfaceLinkStrategyMapper.deleteByInterfaceIds(Collections.singleton(id));
        return gatewayInterfaceInfoMapper.deleteGatewayInterfaceInfoById(id);
    }

    @Override
    public int updateGatewayInterfaceInfoStatusByIds(Collection<Long> ids, GatewayDataStatus status) {
        if (CollectionUtils.isEmpty(ids) || status == null){
            log.warn("Insufficient update conditions");
            return 0;
        }
        return gatewayInterfaceInfoMapper.updateGatewayInterfaceInfoStatusByIds(ids,status.getCode());
    }

    @Override
    public List<GatewayInterfaceInfo> selectGatewayInterfaceInfoByServerIds(Collection<Long> serverIds) {
        if (CollectionUtils.isEmpty(serverIds)){
            return Collections.emptyList();
        }
        return gatewayInterfaceInfoMapper.selectGatewayInterfaceInfoByServerIds(serverIds);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long insertGatewayInterfaceInfoAndBindStrategy(InsertGatewayInterfaceInfoDTO dto) {
        GatewayInterfaceInfo gatewayInterfaceInfo = new GatewayInterfaceInfo();
        gatewayInterfaceInfo.setInterfaceName(dto.getInterfaceName());
        gatewayInterfaceInfo.setInterfacePath(dto.getInterfacePath());
        gatewayInterfaceInfo.setRequestMethod(dto.getRequestMethod());
        gatewayInterfaceInfo.setDescription(dto.getDescription());
        gatewayInterfaceInfo.setVersion(dto.getVersion());
        gatewayInterfaceInfo.setStatus(dto.getStatus());
        gatewayInterfaceInfo.setDocument(dto.getDocument());
        gatewayInterfaceInfo.setServerId(dto.getServerId());
        Long interfaceInfoId = insertGatewayInterfaceInfo(gatewayInterfaceInfo);
        if (CollUtil.isNotEmpty(dto.getStrategyIds())){
            checkGatewayStrategyTypeCannotBeRepeated(dto.getStrategyIds());
            List<GatewayInterfaceLinkStrategy> linkStrategyList = dto.getStrategyIds()
                    .stream().map(strategyId -> new GatewayInterfaceLinkStrategy(interfaceInfoId, strategyId))
                    .collect(Collectors.toList());
            gatewayInterfaceLinkStrategyMapper.batchInsertGatewayInterfaceLinkStrategy(linkStrategyList);
        }
        return interfaceInfoId;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long updateGatewayInterfaceInfoAndBindStrategy(UpdateGatewayInterfaceInfoDTO dto) {
        GatewayInterfaceInfo gatewayInterfaceInfo = new GatewayInterfaceInfo();
        gatewayInterfaceInfo.setId(dto.getId());
        gatewayInterfaceInfo.setInterfaceName(dto.getInterfaceName());
        gatewayInterfaceInfo.setInterfacePath(dto.getInterfacePath());
        gatewayInterfaceInfo.setRequestMethod(dto.getRequestMethod());
        gatewayInterfaceInfo.setDescription(dto.getDescription());
        gatewayInterfaceInfo.setVersion(dto.getVersion());
        gatewayInterfaceInfo.setStatus(dto.getStatus());
        gatewayInterfaceInfo.setDocument(dto.getDocument());
        gatewayInterfaceInfo.setServerId(dto.getServerId());
        updateGatewayInterfaceInfo(gatewayInterfaceInfo);
        // 先删除
        gatewayInterfaceLinkStrategyMapper.deleteByInterfaceIds(Collections.singleton(dto.getId()));
        if (CollUtil.isNotEmpty(dto.getStrategyIds())){
            checkGatewayStrategyTypeCannotBeRepeated(dto.getStrategyIds());
            List<GatewayInterfaceLinkStrategy> linkStrategyList = dto.getStrategyIds()
                    .stream().map(strategyId -> new GatewayInterfaceLinkStrategy(dto.getId(), strategyId))
                    .collect(Collectors.toList());
            gatewayInterfaceLinkStrategyMapper.batchInsertGatewayInterfaceLinkStrategy(linkStrategyList);
        }
        return gatewayInterfaceInfo.getId();
    }

    @Override
    public List<GatewayInterfaceLinkStrategy> selectGatewayInterfaceLinkStrategyByInterfaceIds(Collection<Long> interfaceIds) {
        if (CollectionUtils.isEmpty(interfaceIds)){
            return Collections.emptyList();
        }
        return gatewayInterfaceLinkStrategyMapper.selectGatewayInterfaceLinkStrategyByInterfaceIds(interfaceIds);
    }

    private void checkGatewayStrategyTypeCannotBeRepeated(List<Long> strategyIds) {
        List<GatewayStrategy> strategyList = gatewayStrategyService.selectGatewayStrategyByIds(strategyIds);
        Map<String, List<GatewayStrategy>> groupByStrategyTypeMap = strategyList.stream().collect(Collectors.groupingBy(GatewayStrategy::getStrategyType));
        groupByStrategyTypeMap.forEach((type,strategies) ->{
            Assert.isTrue(strategies.size() == 1, Objects.requireNonNull(GatewayStrategyType.getByCode(type)).getInfo() + "类型只能选择一个！");
        });
    }

}
