package com.hr.service.impl;

import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.hr.dto.AggregateQueryDTO;
import com.hr.param.AccountInterfaceParam;
import com.hr.param.InterfaceConfigParam;
import com.hr.param.SwitchStatusParam;
import com.hr.repository.domain.IpAccountPO;
import com.hr.repository.domain.IpInterfacePO;
import com.hr.repository.domain.IpTokenInterfacePO;
import com.hr.repository.domain.IpTokenPO;
import com.hr.repository.jpa.IpAccountRepository;
import com.hr.repository.jpa.IpInterfaceRepository;
import com.hr.repository.jpa.IpTokenInterfaceRepository;
import com.hr.repository.jpa.IpTokenRepository;
import com.hr.service.IpAccountService;
import com.hr.service.IpTokenInterfaceService;
import com.hr.util.SnowflakeIdWorker;
import com.hr.vo.AccountInterfaceVO;
import com.hr.vo.IpAccountVO;
import com.hr.vo.IpTokenInterfaceVO;
import com.yy.basedevelop.common.data.BasePageResult;
import com.yy.basedevelop.common.util.ruoyi.utils.DateUtils;
import com.yy.basedevelop.dto.LoginUser;
import jakarta.persistence.criteria.Predicate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

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

/**
 * token与接口关系表;(ip_token_interface)表服务接口实现类
 * @author : http://www.yonsum.com
 * @date : 2025-10-10
 */
@Slf4j
@Service
public class IpTokenInterfaceServiceImpl implements IpTokenInterfaceService {
    @Autowired
    private IpTokenInterfaceRepository ipTokenInterfaceRepository;
    @Autowired
    private IpTokenRepository ipTokenRepository;
    @Autowired
    private IpInterfaceRepository ipInterfaceRepository;

    private static final Cache<String, AggregateQueryDTO> QUERY_CACHE = CacheBuilder.newBuilder()
            .expireAfterWrite(1, TimeUnit.SECONDS)
            .build();
    @Autowired
    private IpAccountService ipAccountService;
    @Autowired
    private IpAccountRepository ipAccountRepository;
    @Autowired
    private ParameterNamesModule parameterNamesModule;

    /** 
     * 通过ID查询单条数据 
     *
     * @param tiid 主键
     * @return 实例对象
     */
    public IpTokenInterfaceVO queryById(Long tiid){
        IpTokenInterfacePO ipTokenInterfacePO = ipTokenInterfaceRepository.findById(tiid).get();
        IpTokenInterfaceVO ipTokenInterfaceVO = new IpTokenInterfaceVO();
        if(ipTokenInterfacePO != null){
            BeanUtils.copyProperties(ipTokenInterfacePO, ipTokenInterfaceVO);
            return ipTokenInterfaceVO;
        }
        return null;
    }

    
    /** 
     * 新增数据
     *
     * @param IpTokenInterfacePO 实例对象
     * @return 实例对象
     */
    public void insert(IpTokenInterfacePO IpTokenInterfacePO){
        ipTokenInterfaceRepository.save(IpTokenInterfacePO);
    }
    
    /** 
     * 更新数据
     *
     * @param IpTokenInterfacePO 实例对象
     * @return 实例对象
     */
    public void update(IpTokenInterfacePO IpTokenInterfacePO){
        ipTokenInterfaceRepository.save(IpTokenInterfacePO);
    }

     @Override
     public Page<IpTokenInterfacePO> paginQuery(IpTokenInterfacePO ipTokenInterfacePO, Integer current, Integer size) {
         ExampleMatcher matcher = ExampleMatcher.matchingAll()
                 .withIgnoreNullValues()                              // 忽略 null 字段
                 .withIgnoreCase();
         Pageable pageAble = PageRequest.of(current, size);
         Example<IpTokenInterfacePO> example = Example.of(ipTokenInterfacePO, matcher);
         Page<IpTokenInterfacePO> result = ipTokenInterfaceRepository.findAll(example, pageAble);
         return result;
     }

    @Override
    public Boolean switchStatus(SwitchStatusParam switchStatusParam) {
        Optional<IpTokenInterfacePO> optional = ipTokenInterfaceRepository.findById(switchStatusParam.getId());
        if(!optional.isPresent()){
            throw new RuntimeException("记录不存在");
        }
        IpTokenInterfacePO ipTokenInterfacePO = optional.get();
        Long iid = ipTokenInterfacePO.getIid();
        IpInterfacePO ipInterfacePO = ipInterfaceRepository.findById(iid).get();
        if ("delete".equals(ipInterfacePO.getStatus()) && "normal".equals(switchStatusParam.getStatus())) {
            throw new RuntimeException("接口已被删除，无法启用");
        }
        ipTokenInterfacePO.setStatus(switchStatusParam.getStatus());
        ipTokenInterfaceRepository.save(ipTokenInterfacePO);
        return true;
    }

    @Override
    public BasePageResult<AccountInterfaceVO> accountInterfaceList(AccountInterfaceParam pageParam) {
        if(!StringUtils.isEmpty(pageParam.getAccNo())){
            IpAccountPO accountPO = ipAccountRepository.findByAccNo(pageParam.getAccNo());
            if(accountPO != null){
                pageParam.setAid(accountPO.getId());
            }
        }
        List<String> statusList = Arrays.asList("normal", "disable");
        if(StringUtils.isNotEmpty(pageParam.getStatus())){
            statusList = Arrays.asList(pageParam.getStatus());
        }
        PageHelper.startPage(pageParam.getPageNum(), pageParam.getPageSize());
        BasePageResult<IpTokenInterfacePO> content = ipTokenInterfaceRepository.queryList(pageParam.getAid(),statusList);
        List<Long> tokenIdList = new ArrayList<>();
        List<Long> interfaceIdList = new ArrayList<>();
        for (IpTokenInterfacePO interfacePO : content) {
            tokenIdList.add(interfacePO.getTid());
            interfaceIdList.add(interfacePO.getIid());
        }
        Map<Long, IpTokenPO> tokenMap = new HashMap<>();
        Map<Long, IpInterfacePO> interfaceMap = new HashMap<>();
        if(!tokenIdList.isEmpty()){
            Specification<IpTokenPO> spec = (root, query, cb) -> {
                return root.get("id").in(tokenIdList);
            };
            List<IpTokenPO> ipTokenList = ipTokenRepository.findAll(spec);
            for (IpTokenPO ipTokenPO : ipTokenList) {
                tokenMap.put(ipTokenPO.getId(), ipTokenPO);
            }
        }

        if(!interfaceIdList.isEmpty()){
            Specification<IpInterfacePO> spec = (root, query, cb) -> {
                return root.get("id").in(interfaceIdList);
            };
            List<IpInterfacePO> ipInterfacePOList = ipInterfaceRepository.findAll(spec);
            for (IpInterfacePO interfacePO : ipInterfacePOList) {
                interfaceMap.put(interfacePO.getId(), interfacePO);
            }
        }
        List<AccountInterfaceVO> resultList = content.stream().map(item -> {
            AccountInterfaceVO vo = new AccountInterfaceVO();
            BeanUtils.copyProperties(item, vo);
            IpTokenPO ipTokenPO = tokenMap.get(item.getTid());
            vo.setSecret(ipTokenPO.getSecret());
            vo.setToken(ipTokenPO.getToken());
            vo.setRemark(ipTokenPO.getRemark());
            IpInterfacePO ipInterfacePO = interfaceMap.get(item.getIid());
            if(ipInterfacePO != null){
                vo.setInterfaceCode(ipInterfacePO.getInterfaceNo());
                vo.setInterfaceName(ipInterfacePO.getInterfaceName());
                vo.setInterfaceId(ipInterfacePO.getId());
                vo.setManufacturer(ipInterfacePO.getManufacturer());
            }
            vo.setCallback(item.getIsCallback());
            vo.setCallbackUrl(item.getCallbackUrl());
            return vo;
        }).toList();
        BasePageResult<AccountInterfaceVO> resultPage = new BasePageResult<>(resultList,content.getTotal(),content.getPage(), content.getPageSize());
        return resultPage;

    }

    @Override
    public AggregateQueryDTO queryConfigByInterfaceCodeAndAccountNo(Long accountId, Long interfaceId) {
        String key = "queryConfigByInterfaceCodeAndAccountNo:" + accountId + ":" + interfaceId;
        AggregateQueryDTO aggregateQueryDTO = QUERY_CACHE.getIfPresent(key);
        if(aggregateQueryDTO != null){
            return aggregateQueryDTO;
        }else{
            AggregateQueryDTO resultDTO = new AggregateQueryDTO();
            ExampleMatcher matcher = ExampleMatcher.matchingAll()
                    .withIgnoreNullValues()                              // 忽略 null 字段
                    .withMatcher("aid", ExampleMatcher.GenericPropertyMatchers.exact())
                    .withMatcher("iid", ExampleMatcher.GenericPropertyMatchers.exact())
                    .withIgnoreCase();
            IpTokenInterfacePO po = new IpTokenInterfacePO();
            po.setAid(accountId);
            po.setIid(interfaceId);
            po.setStatus("normal");
            Example<IpTokenInterfacePO> example = Example.of(po, matcher);
            List<IpTokenInterfacePO> interfacePOList = ipTokenInterfaceRepository.findAll(example);
            log.info("interfacePOList:{},{},{}",accountId,interfaceId,interfacePOList);
            if(!interfacePOList.isEmpty()){
                IpTokenInterfacePO first = interfacePOList.getFirst();
                Long tid = first.getTid();
                IpTokenPO ipTokenPO = ipTokenRepository.findById(tid).get();
                resultDTO.setIpTokenPO(ipTokenPO);
                resultDTO.setIpTokenInterfacePO(first);
            }
            QUERY_CACHE.put(key, resultDTO);
            return resultDTO;
        }
    }

    @Override
    public void delAccountInterface(Long id, LoginUser user) {
        Optional<IpTokenInterfacePO> ipTokenInterfacePOOptional = ipTokenInterfaceRepository.findById(id);
        if(!ipTokenInterfacePOOptional.isPresent()){
            throw new RuntimeException("参数异常");
        }
        IpTokenInterfacePO ipTokenInterfacePO = ipTokenInterfacePOOptional.get();
        Long tid = ipTokenInterfacePO.getTid();
        IpTokenPO ipTokenPO = ipTokenRepository.findById(tid).get();
        ipTokenPO.setUpdateUserId(user.getUserid());
        ipTokenPO.setUpdateUserName(user.getUsername());
        ipTokenPO.setUpdateTime(new Date());
        ipTokenPO.setStatus("delete");
        ipTokenRepository.save(ipTokenPO);

        ipTokenInterfacePO.setUpdateUserId(user.getUserid());
        ipTokenInterfacePO.setUpdateUserName(user.getUsername());
        ipTokenInterfacePO.setUpdateTime(new Date());
        ipTokenInterfacePO.setStatus("delete");
        ipTokenInterfaceRepository.save(ipTokenInterfacePO);

    }

    @Override
    public void interfaceConfig(InterfaceConfigParam param, LoginUser user) {
        String token = param.getToken();
        Long id = param.getId();
        Date now = new Date();
        IpTokenInterfacePO ipTokenInterfacePO;
        IpTokenPO ipTokenPO;
        // 校验唯一性
        if(id != null){
            List<IpTokenInterfacePO> interfaceList = ipTokenInterfaceRepository.queryRefList(param.getAccountId(), param.getInterfaceId());
            if(!interfaceList.isEmpty()){
                for (IpTokenInterfacePO tokenInterfacePO : interfaceList) {
                    if(!tokenInterfacePO.getId().equals(id)){
                        throw new RuntimeException("该账号下已存在对应接口");
                    }
                }
            }

            ipTokenInterfacePO = ipTokenInterfaceRepository.findById(param.getId()).get();
            ipTokenPO = ipTokenRepository.findById(ipTokenInterfacePO.getTid()).get();
            if(ipTokenPO == null){
                throw new RuntimeException("参数异常");
            }
            Optional<IpTokenInterfacePO> optional = ipTokenInterfaceRepository.findById(id);
            if(!optional.isPresent()){
                throw new RuntimeException("参数异常");
            }
        }else{
            List<IpTokenInterfacePO> interfaceList = ipTokenInterfaceRepository.queryRefList(param.getAccountId(), param.getInterfaceId());
            if(!interfaceList.isEmpty()){
                throw new RuntimeException("该账号下已存在对应接口");
            }


            ipTokenInterfacePO = new IpTokenInterfacePO();
            ipTokenPO = new IpTokenPO();
            ipTokenInterfacePO.setAid(param.getAccountId());
            ipTokenInterfacePO.setIid(param.getInterfaceId());
            ipTokenInterfacePO.setAddTime(now);
            ipTokenInterfacePO.setAddUserId(user.getUserid());
            ipTokenInterfacePO.setAddUserName(user.getUsername());
            ipTokenInterfacePO.setId(SnowflakeIdWorker.nextId());
            ipTokenPO.setAddUserId(user.getUserid());
            ipTokenPO.setAddUserName(user.getUsername());
            ipTokenPO.setAid(param.getAccountId());
            ipTokenPO.setId(SnowflakeIdWorker.nextId());
            ipTokenPO.setAddTime(new Date());
            ipTokenInterfacePO.setTid(ipTokenPO.getId());
        }
        ipTokenPO.setRemark(param.getRemark());
        ipTokenPO.setToken(token);
        ipTokenPO.setSecret(param.getSecret());
        ipTokenPO.setUpdateTime(now);
        ipTokenPO.setStatus(param.getStatus());
        ipTokenPO.setUpdateUserName(user.getUsername());
        ipTokenPO.setUpdateUserId(user.getUserid());
        ipTokenRepository.save(ipTokenPO);
        ipTokenInterfacePO.setIid(param.getInterfaceId());
        ipTokenInterfacePO.setUpdateTime(now);
        ipTokenInterfacePO.setStatus(param.getStatus());
        ipTokenInterfacePO.setUpdateUserName(user.getUsername());
        ipTokenInterfacePO.setUpdateUserId(user.getUserid());
        ipTokenInterfacePO.setCallbackNum(param.getCallbackNum() == null ? 0 : param.getCallbackNum());
        ipTokenInterfacePO.setIsCallback(param.getCallback());
        ipTokenInterfacePO.setCallbackUrl(param.getCallbackUrl());
        ipTokenInterfaceRepository.save(ipTokenInterfacePO);
    }

    /**
     * 通过主键删除数据
     *
     * @param tiid 主键
     * @return 是否成功
     */
    public boolean deleteById(Long tiid){
        ipTokenInterfaceRepository.deleteById(tiid);
        return true;
    }
}