package com.sunyard.chsm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sunyard.chsm.config.IpFilter;
import com.sunyard.chsm.dto.IpWhitelistDTO;
import com.sunyard.chsm.enums.EnableStatus;
import com.sunyard.chsm.mapper.IpWhitelisttMapper;
import com.sunyard.chsm.model.entity.IpWhitelist;
import com.sunyard.chsm.service.IpWhitelistService;
import com.sunyard.chsm.utils.IpUtils;
import com.sunyard.ssp.utils.SecurityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * @author liulu
 * @since 2024/11/22
 */
@Slf4j
@Service
@Transactional
public class IpWhitelistServiceImpl implements IpWhitelistService {

    private static final String global = "global";
    private static final String app = "app";

    @Resource
    private IpWhitelisttMapper ipWhitelisttMapper;
    @Resource
    private SecurityUtil securityUtil;


    @Override
    public Page<IpWhitelistDTO.IpView> selectPageList(IpWhitelistDTO.Query query) {

        LambdaQueryWrapper<IpWhitelist> wrapper = new LambdaQueryWrapper<IpWhitelist>()
                .eq(IpWhitelist::getScope, global)
                .eq(StringUtils.hasText(query.getIpAddress()), IpWhitelist::getIp, query.getIpAddress())

                .orderByDesc(IpWhitelist::getCreateTime);
        if (Objects.nonNull(query.getStartDate())) {
            wrapper.gt(IpWhitelist::getCreateTime, LocalDateTime.of(query.getStartDate(), LocalTime.MIN));
        }
        if (Objects.nonNull(query.getEndDate())) {
            wrapper.lt(IpWhitelist::getCreateTime, LocalDateTime.of(query.getEndDate(), LocalTime.MAX));
        }
        if (Objects.nonNull(query.getStatus())) {
            wrapper.eq(IpWhitelist::getStatus, query.getStatus() == 0 ? EnableStatus.ENABLED.getCode() : EnableStatus.DISABLED.getCode());
        }
        IPage<IpWhitelist> page = ipWhitelisttMapper.selectPage(
                new Page<>(query.getPageNumber(), query.getPageSize()),
                wrapper
        );
        List<IpWhitelist> records = page.getRecords();
        if (CollectionUtils.isEmpty(records)) {
            return new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        }
        List<IpWhitelistDTO.IpView> viewList = records.stream()
                .map(it -> {
                    IpWhitelistDTO.IpView view = new IpWhitelistDTO.IpView();
                    view.setId(it.getId());
                    view.setIpAddress(it.getIp());
                    view.setStatus(-EnableStatus.of(it.getStatus()).ordinal());
                    view.setCreator(it.getCreator());
                    view.setMemo(it.getRemark());
                    view.setCreateTime(it.getCreateTime());
                    return view;
                })
                .collect(Collectors.toList());

        return new Page<IpWhitelistDTO.IpView>(page.getCurrent(), page.getSize(), page.getTotal()).setRecords(viewList);
    }

    @Override
    public Long save(IpWhitelistDTO.IpSave save) {

        Assert.notNull(save.getIpAddress(), "IP地址不能为空");
        IpWhitelist exist = ipWhitelisttMapper.selectOne(
                new LambdaQueryWrapper<IpWhitelist>().eq(IpWhitelist::getIp, save.getIpAddress())
        );
        Assert.isNull(exist, "此ip已经存在");

        IpWhitelist whitelist = new IpWhitelist();
        whitelist.setId(IdWorker.getId());
        whitelist.setAppId(0L);
        whitelist.setIp(save.getIpAddress());
        whitelist.setScope(global);
        whitelist.setStatus(EnableStatus.ENABLED.getCode());
        whitelist.setCreator(securityUtil.getCurrUser().getRealname());
        whitelist.setCreateTime(LocalDateTime.now());
        whitelist.setRemark(save.getMemo());

        ipWhitelisttMapper.insert(whitelist);
        IpFilter.whiteIps.add(save.getIpAddress());

        return whitelist.getId();
    }


    @Override
    public void update(IpWhitelistDTO.IpSave update) {

        Assert.notNull(update.getId(), "id不能为空");

        IpWhitelist exist = ipWhitelisttMapper.selectById(update.getId());
        Assert.notNull(exist, "要更新的数据不存在");

        if (StringUtils.hasText(update.getIpAddress())
                && !Objects.equals(update.getIpAddress(), exist.getIp())) {
            IpWhitelist check = ipWhitelisttMapper.selectOne(
                    new LambdaQueryWrapper<IpWhitelist>().eq(IpWhitelist::getIp, update.getIpAddress())
            );
            Assert.isNull(check, "此ip已经存在");
        }
        IpWhitelist whitelist = new IpWhitelist();
        whitelist.setId(update.getId());
        whitelist.setIp(update.getIpAddress());
        whitelist.setStatus(update.getStatus() == 0 ? EnableStatus.ENABLED.getCode() : EnableStatus.DISABLED.getCode());
        whitelist.setUpdateTime(LocalDateTime.now());
        whitelist.setRemark(update.getMemo());
        if (!Objects.equals(exist.getStatus(), whitelist.getStatus())) {
            if (EnableStatus.ENABLED.getCode().equals(whitelist.getStatus())) {
                IpFilter.whiteIps.add(update.getIpAddress());
            } else {
                IpFilter.whiteIps.remove(update.getIpAddress());
            }
        }

        ipWhitelisttMapper.updateById(whitelist);
    }

    @Override
    public void delete(Long[] ids) {
        for (Long id : ids) {
            IpWhitelist whitelist = ipWhitelisttMapper.selectById(id);
            if (whitelist != null) {
                ipWhitelisttMapper.deleteById(id);
                IpFilter.whiteIps.remove(whitelist.getIp());
            }
        }
    }

    @Override
    public void enableWhiteIpEvent() {

        ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = servletRequestAttributes.getRequest();
        String ip = IpUtils.getIpAddress(request);
        IpWhitelist whiteIP = ipWhitelisttMapper.selectOne(
                new LambdaQueryWrapper<IpWhitelist>().eq(IpWhitelist::getIp, ip).eq(IpWhitelist::getScope, global)
        );
        if (whiteIP == null) {
            IpWhitelist whitelist = new IpWhitelist();
            whitelist.setId(IdWorker.getId());
            whitelist.setAppId(0L);
            whitelist.setIp(ip);
            whitelist.setScope(global);
            whitelist.setStatus(EnableStatus.ENABLED.getCode());
            whitelist.setCreator(securityUtil.getCurrUser().getRealname());
            whitelist.setCreateTime(LocalDateTime.now());
            whitelist.setRemark("enableWhitelist");
            ipWhitelisttMapper.insert(whitelist);
        } else {
            IpWhitelist up = new IpWhitelist();
            up.setId(whiteIP.getId());
            up.setStatus(EnableStatus.ENABLED.getCode());
            ipWhitelisttMapper.updateById(up);
        }
    }
}
