package cd.casic.module.machine.service.impl;

import cd.casic.framework.commons.pojo.PageResult;
import cd.casic.module.machine.controller.vo.MachineProxyVO;
import cd.casic.module.machine.dal.dataobject.MachineProxyDO;
import cd.casic.module.machine.enums.MachineProxyStatus;
import cd.casic.module.machine.enums.MachineProxyType;
import cd.casic.module.machine.dal.mysql.MachineProxyMapper;
import cd.casic.module.machine.service.MachineProxyService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.annotations.VisibleForTesting;
import jakarta.annotation.Resource;
import cd.casic.framework.commons.util.object.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

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

import static cd.casic.framework.commons.exception.util.ServiceExceptionUtil.exception;
import static cd.casic.module.machine.contants.MachineErrorCodeConstants.*;
import static com.baomidou.mybatisplus.extension.toolkit.Db.save;

/**
 * 机器代理服务实现类
 */
@Service("machineProxyService")
public class MachineProxyServiceImpl implements MachineProxyService {
    @Resource
    private MachineProxyMapper machineProxyMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createProxy(MachineProxyVO machineProxyVO) {
        validateMachineProxyAdd(machineProxyVO);
        // 创建代理记录
        MachineProxyDO machineProxyDO = BeanUtils.toBean(machineProxyVO, MachineProxyDO.class);
        save(machineProxyDO);
        return machineProxyDO.getId();
    }

    @Override
    public void updateProxy(MachineProxyVO machineProxyVO) {
        // 参数校验
        MachineProxyDO machineProxyDO = validateMachineProxyExists(machineProxyVO.getId());
        // 更新状态
        BeanUtils.copyProperties(machineProxyVO, machineProxyDO);
        machineProxyMapper.updateById(machineProxyDO);
    }

    @Override
    public void delete(Long id) {
        MachineProxyDO machineProxyDO = validateMachineProxyExists(id);
        validateMachineProxyOnline(machineProxyDO);
        machineProxyMapper.deleteById(id);
    }

    @VisibleForTesting
    void validateMachineProxyOnline(MachineProxyDO machineProxyDO) {
        if (machineProxyDO.getStatus() == MachineProxyStatus.ONLINE.getCode()) {
            throw exception(MACHINE_PROXY_IS_ONLINE);
        }
    }

    @Override
    public Map<Integer, Long> getAllProxyStatus() {
        List<MachineProxyDO> proxyList = machineProxyMapper.selectList(new QueryWrapper<>());
        if (CollectionUtils.isEmpty(proxyList)) {
            return Collections.emptyMap();
        }
        return proxyList.stream()
            .map(MachineProxyDO::getStatus)
            .collect(Collectors.groupingBy(
                Function.identity(),
                // 统计每个分组的元素数量
                Collectors.counting()
            ));
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteProxyList(String ids) {
        if (ids == null) {
            return;
        }
        List<Long> machineProxyIds = Arrays.stream(ids.split(","))
            .map(String::trim)
            .filter(s -> !s.isEmpty())
            .map(Long::parseLong)
            .toList();
        // 批量逻辑删除
        machineProxyIds.forEach(this::delete);
    }

    @Override
    public PageResult<MachineProxyDO> getProxyPage(MachineProxyVO machineProxyVO) {
        return machineProxyMapper.selectPage(machineProxyVO);
    }

    @VisibleForTesting
    MachineProxyDO validateMachineProxyExists(Long id) {
        if (id == null) {
            throw exception(MACHINE_PROXY_NOT_EXISTS);
        }
        MachineProxyDO machineProxyDO = machineProxyMapper.selectById(id);
        if (machineProxyDO == null) {
            throw exception(MACHINE_PROXY_NOT_EXISTS);
        }
        return machineProxyDO;
    }

    @VisibleForTesting
    void validateMachineProxyAdd(MachineProxyVO machineProxyVO) {
        if (machineProxyVO.getHostIp() == null) {
            throw exception(MACHINE_PROXY_HOST_IP_NULL);
        }
        if (machineProxyVO.getUsername() == null) {
            throw exception(MACHINE_PROXY_USER_NAME_NULL);
        }

        // 校验代理类型
        int[] arrays = MachineProxyType.ARRAYS;
        if (Arrays.stream(arrays).filter(i -> i == machineProxyVO.getProxyType()).findAny().isEmpty()) {
            throw exception(MACHINE_PROXY_TYPE_NOT_EXISTS);
        }
    }

}
