package com.ssyf.module.robot.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ssyf.common.security.domain.ClientInfo;
import com.ssyf.common.security.helper.ClientContextHelper;
import com.ssyf.common.web.apicode.ApiCodeUser;
import com.ssyf.common.web.error.ServiceRuntimeException;
import com.ssyf.module.robot.domain.entity.ChatConfig;
import com.ssyf.module.robot.domain.entity.RRobotAccount;
import com.ssyf.module.robot.domain.entity.RRobotGroup;
import com.ssyf.module.robot.domain.query.ChatConfigQuery;
import com.ssyf.module.robot.domain.query.RRobotAccountQuery;
import com.ssyf.module.robot.service.ChatConfigService;
import com.ssyf.module.robot.service.RRobotAccountService;
import com.ssyf.module.robot.service.RRobotGroupService;
import com.ssyf.module.robot.mapper.ChatConfigMapper;
import com.ssyf.plugs.mysql.helper.MybatisPlusHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
* @author ELSA
* @description 针对表【chat_config(聊天配置表)】的数据库操作Service实现
* @createDate 2026-01-31 10:08:46
*/
@Service
public class ChatConfigServiceImpl extends ServiceImpl<ChatConfigMapper, ChatConfig>
    implements ChatConfigService{

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    
    @Autowired
    private RRobotGroupService robotGroupService;
    
    @Autowired
    private RRobotAccountService robotAccountService;
    
    private static final String CACHE_KEY_PREFIX = "chat_config:";
    private static final String CACHE_KEY_AVAILABLE_PREFIX = "chat_config_available:";
    private static final long CACHE_EXPIRE_HOURS = 24;

    @Override
    public ChatConfig addOne(ChatConfigQuery query) {
        // 参数校验
        if(StrUtil.isBlank(query.getName())){
            ServiceRuntimeException.throw0(ApiCodeUser.PARAMETER_ERROR.getCode() , "配置名称不能为空");
        }
        
        // 处理分组和机器人名称
        handleGroupAndRobotNames(query);
        
        ClientInfo clientInfo = ClientContextHelper.getClientInfo();
        ChatConfig entity = BeanUtil.toBean(query ,ChatConfig.class);
        entity.setUuid(IdUtil.simpleUUID());
        entity.setCreatorUuid(clientInfo.getId().toString()).setCreator(clientInfo.getNickname())
                .setCreateTime(LocalDateTime.now());
        this.save(entity);
        
        // 新增成功后清除相关可用配置缓存
        clearAvailableConfigCache(entity);
        
        return entity;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void removeByUid(String uuid) {
        ChatConfig config = checkedExistAndGet(uuid);
        this.remove(createBaseWrapper(null).eq(ChatConfig::getUuid, uuid));
        
        // 删除成功后清除缓存
        String cacheKey = CACHE_KEY_PREFIX + uuid;
        redisTemplate.delete(cacheKey);
        
        // 清除相关可用配置缓存
        clearAvailableConfigCache(config);
    }

    @Override
    public void removeBatchByUids(List<String> uuids) {
        // 先查询所有配置，用于后续清除缓存
        List<ChatConfig> configs = this.list(createBaseWrapper(null).in(ChatConfig::getUuid, uuids));
        
        this.remove(createBaseWrapper(null).in(ChatConfig::getUuid, uuids));
        
        // 批量删除成功后清除缓存
        for (String uuid : uuids) {
            String cacheKey = CACHE_KEY_PREFIX + uuid;
            redisTemplate.delete(cacheKey);
        }
        
        // 清除相关可用配置缓存
        for (ChatConfig config : configs) {
            clearAvailableConfigCache(config);
        }
    }

    @Override
    public void updateByUid(String uuid, ChatConfigQuery query) {
        ChatConfig oldConfig = this.checkedExistAndGet(uuid);
        query.setUuid(null);
        
        // 处理分组和机器人名称
        handleGroupAndRobotNames(query);
        
        ChatConfig update = BeanUtil.toBean(query ,ChatConfig.class);
        LambdaQueryWrapper<ChatConfig> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ChatConfig::getUuid, uuid);
        this.update(update , wrapper);
        
        // 更新成功后清除缓存，下次查询时会重新加载
        String cacheKey = CACHE_KEY_PREFIX + uuid;
        redisTemplate.delete(cacheKey);
        
        // 清除相关可用配置缓存
        clearAvailableConfigCache(oldConfig);
        
        // 如果机器人UUID或分组UUID发生变化，还需要清除新的相关缓存
        if ((oldConfig.getRobotUuid() != null && !oldConfig.getRobotUuid().equals(update.getRobotUuid())) ||
            (oldConfig.getRobotGroupUuid() != null && !oldConfig.getRobotGroupUuid().equals(update.getRobotGroupUuid()))) {
            clearAvailableConfigCache(update);
        }
    }

    @Override
    public ChatConfig getOneByUid(String uuid) {
        String cacheKey = CACHE_KEY_PREFIX + uuid;
        
        // 先尝试从缓存获取
        ChatConfig cachedConfig = (ChatConfig) redisTemplate.opsForValue().get(cacheKey);
        if (cachedConfig != null) {
            return cachedConfig;
        }
        
        // 缓存未命中，查询数据库
        ChatConfig config = this.getOne(createBaseWrapper(null).eq(ChatConfig::getUuid, uuid));
        
        // 如果查询到结果，存入缓存
        if (config != null) {
            redisTemplate.opsForValue().set(cacheKey, config, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        }
        
        return config;
    }

    @Override
    public PageInfo<ChatConfig> getPage(ChatConfigQuery query) {
        PageHelper.startPage(query.getPageNum(), query.getPageSize());
        return PageInfo.of(this.list(createBaseWrapper(query)));
    }

    @Override
    public List<ChatConfig> getList(ChatConfigQuery query) {
        return this.list(createBaseWrapper(query));
    }

    @Override
    public ChatConfig checkedExistAndGet(String uuid) {
        ChatConfig old = this.getOne(createBaseWrapper(null).eq(ChatConfig::getUuid, uuid));
        if (old == null) {
            ServiceRuntimeException.throw0(ApiCodeUser.PARAMETER_ERROR.getCode(), "数据不存在");
        }
        return old;
    }

    @Override
    public Integer countBy(ChatConfigQuery query) {
        return this.count(createBaseWrapper(query));
    }

    private LambdaQueryWrapper<ChatConfig> createBaseWrapper(ChatConfigQuery query) {
        LambdaQueryWrapper<ChatConfig> wrapper = new LambdaQueryWrapper<>();
        if (query == null) {
            return wrapper;
        }
        wrapper.like(StrUtil.isNotBlank(query.getUuid()), ChatConfig::getUuid, query.getUuid());
        wrapper.like(StrUtil.isNotBlank(query.getName()), ChatConfig::getName, query.getName());
        wrapper.like(StrUtil.isNotBlank(query.getNotes()), ChatConfig::getNotes, query.getNotes());
        wrapper.like(StrUtil.isNotBlank(query.getRobotGroupUuid()), ChatConfig::getRobotGroupUuid, query.getRobotGroupUuid());
        wrapper.like(StrUtil.isNotBlank(query.getRobotGroupName()), ChatConfig::getRobotGroupName, query.getRobotGroupName());
        wrapper.like(StrUtil.isNotBlank(query.getRobotUuid()), ChatConfig::getRobotUuid, query.getRobotUuid());
        wrapper.like(StrUtil.isNotBlank(query.getRobotName()), ChatConfig::getRobotName, query.getRobotName());
        wrapper.ge(query.getMinIntervalTime() != null, ChatConfig::getMinIntervalTime, query.getMinIntervalTime());
        wrapper.le(query.getMaxIntervalTime() != null, ChatConfig::getMaxIntervalTime, query.getMaxIntervalTime());
        wrapper.eq(query.getCount() != null, ChatConfig::getCount, query.getCount());
        wrapper.eq(query.getStatus() != null, ChatConfig::getStatus, query.getStatus());
        wrapper.eq(query.getAiSwitch() != null, ChatConfig::getAiSwitch, query.getAiSwitch());
        wrapper.like(StrUtil.isNotBlank(query.getOpeningRemarks()), ChatConfig::getOpeningRemarks, query.getOpeningRemarks());
        wrapper.ge(query.getCreateTimeStart() != null, ChatConfig::getCreateTime, query.getCreateTimeStart());
        wrapper.le(query.getCreateTimeEnd() != null, ChatConfig::getCreateTime, query.getCreateTimeEnd());
        wrapper.like(StrUtil.isNotBlank(query.getCreator()), ChatConfig::getCreator, query.getCreator());
        wrapper.eq(StrUtil.isNotBlank(query.getCreatorUuid()), ChatConfig::getCreatorUuid, query.getCreatorUuid());
        
        if (CollectionUtil.isNotEmpty(query.getSorts())) {
            MybatisPlusHelper.orderAndIgnoreError(ChatConfig.class, wrapper, query.getSorts());
        } else {
            wrapper.orderByDesc(ChatConfig::getCreateTime);
        }
        return wrapper;
    }
    
    /**
     * 处理分组和机器人名称
     * 当uuid被更新或新增时确保name变更和有值
     */
    private void handleGroupAndRobotNames(ChatConfigQuery query) {
        // 处理机器人组名称
        if (StrUtil.isNotBlank(query.getRobotGroupUuid())) {
            if (StrUtil.isBlank(query.getRobotGroupName())) {
                // 根据robotGroupUuid查询对应的机器人组名称
                RRobotGroup robotGroup = robotGroupService.getOneByUid(query.getRobotGroupUuid());
                if (robotGroup != null) {
                    query.setRobotGroupName(robotGroup.getGroupName());
                } else {
                    // 如果分组不存在，抛出异常
                    ServiceRuntimeException.throw0(ApiCodeUser.PARAMETER_ERROR.getCode(), "指定的机器人分组不存在");
                }
            }
        } else {
            // 如果uuid为空，则把name设置为空
            query.setRobotGroupName(null);
        }
        
        // 处理机器人名称
        if (StrUtil.isNotBlank(query.getRobotUuid())) {
            if (StrUtil.isBlank(query.getRobotName())) {
                // 根据robotUuid查询对应的机器人名称
                RRobotAccount robotAccount = robotAccountService.getOneByUid(query.getRobotUuid());
                if (robotAccount != null) {
                    query.setRobotName(robotAccount.getEmail()); // 使用邮箱作为机器人名称
                } else {
                    // 如果机器人不存在，抛出异常
                    ServiceRuntimeException.throw0(ApiCodeUser.PARAMETER_ERROR.getCode(), "指定的机器人不存在");
                }
            }
        } else {
            // 如果uuid为空，则把name设置为空
            query.setRobotName(null);
        }
    }

    @Override
    public List<ChatConfig> getAvailableConfigsByRobotUuid(String robotUuid) {
        if (StrUtil.isBlank(robotUuid)) {
            ServiceRuntimeException.throw0(ApiCodeUser.PARAMETER_ERROR.getCode(), "机器人UUID不能为空");
        }

        String cacheKey = CACHE_KEY_AVAILABLE_PREFIX + robotUuid;
        
        // 先尝试从缓存获取
        String cachedConfigsJson = (String) redisTemplate.opsForValue().get(cacheKey);
        if (StrUtil.isNotBlank(cachedConfigsJson)) {
            return JSONUtil.toList(cachedConfigsJson, ChatConfig.class);
        }

        // 缓存未命中，查询数据库
        List<ChatConfig> availableConfigs = queryAvailableConfigsByRobotUuid(robotUuid);
        
        // 如果查询到结果，存入缓存
        if (CollectionUtil.isNotEmpty(availableConfigs)) {
            String configsJson = JSONUtil.toJsonStr(availableConfigs);
            redisTemplate.opsForValue().set(cacheKey, configsJson, CACHE_EXPIRE_HOURS, TimeUnit.HOURS);
        }
        
        return availableConfigs;
    }

    /**
     * 查询可用的聊天配置
     * 优先级：1.机器人UUID匹配的配置 2.机器人分组UUID匹配的配置 3.无机器人和分组UUID的通用配置
     */
    private List<ChatConfig> queryAvailableConfigsByRobotUuid(String robotUuid) {
        // 获取机器人信息以获取分组UUID
        RRobotAccount robotAccount = robotAccountService.getOneByUid(robotUuid);
        if (robotAccount == null) {
            ServiceRuntimeException.throw0(ApiCodeUser.PARAMETER_ERROR.getCode(), "机器人不存在");
        }
        
        String robotGroupUuid = robotAccount.getGroupId();
        
        // 构建查询条件：只查询启用状态的配置
        ChatConfigQuery query = new ChatConfigQuery();
        query.setStatus(1); // 启用状态
        
        // 查询所有启用状态的配置
        List<ChatConfig> allEnabledConfigs = this.getList(query);
        
        if (CollectionUtil.isEmpty(allEnabledConfigs)) {
            return new ArrayList<>();
        }
        
        // 按优先级筛选配置
        List<ChatConfig> robotSpecificConfigs = new ArrayList<>();
        List<ChatConfig> groupSpecificConfigs = new ArrayList<>();
        List<ChatConfig> generalConfigs = new ArrayList<>();
        
        for (ChatConfig config : allEnabledConfigs) {
            if (StrUtil.isNotBlank(config.getRobotUuid()) && config.getRobotUuid().equals(robotUuid)) {
                // 机器人UUID匹配的配置（最高优先级）
                robotSpecificConfigs.add(config);
            } else if (StrUtil.isNotBlank(config.getRobotGroupUuid()) && 
                       StrUtil.isNotBlank(robotGroupUuid) && 
                       config.getRobotGroupUuid().equals(robotGroupUuid)) {
                // 机器人分组UUID匹配的配置（中等优先级）
                groupSpecificConfigs.add(config);
            } else if (StrUtil.isBlank(config.getRobotUuid()) && StrUtil.isBlank(config.getRobotGroupUuid())) {
                // 无机器人和分组UUID的通用配置（最低优先级）
                generalConfigs.add(config);
            }
        }
        
        // 按优先级合并结果
        List<ChatConfig> result = new ArrayList<>();
        result.addAll(robotSpecificConfigs);
        result.addAll(groupSpecificConfigs);
        result.addAll(generalConfigs);
        
        // 按创建时间倒序排列，取最新的配置
        result.sort((c1, c2) -> c2.getCreateTime().compareTo(c1.getCreateTime()));
        
        return result;
    }
    
    /**
     * 清除相关可用配置缓存
     * 根据配置的机器人UUID和分组UUID清除对应的缓存
     */
    private void clearAvailableConfigCache(ChatConfig config) {
        if (config == null) {
            return;
        }
        
        // 清除机器人UUID相关的缓存
        if (StrUtil.isNotBlank(config.getRobotUuid())) {
            String robotCacheKey = CACHE_KEY_AVAILABLE_PREFIX + config.getRobotUuid();
            redisTemplate.delete(robotCacheKey);
        }
        
        // 清除分组UUID相关的缓存
        if (StrUtil.isNotBlank(config.getRobotGroupUuid())) {
            // 获取该分组下的所有机器人UUID
            RRobotAccountQuery query = new RRobotAccountQuery();
            query.setGroupId(config.getRobotGroupUuid());
            List<RRobotAccount> robotAccounts = robotAccountService.getList(query);
            if (CollectionUtil.isNotEmpty(robotAccounts)) {
                for (RRobotAccount robotAccount : robotAccounts) {
                    String robotCacheKey = CACHE_KEY_AVAILABLE_PREFIX + robotAccount.getUuid();
                    redisTemplate.delete(robotCacheKey);
                }
            }
            
            // 清除分组UUID本身的缓存（用于通用配置）
            String groupCacheKey = CACHE_KEY_AVAILABLE_PREFIX + config.getRobotGroupUuid();
            redisTemplate.delete(groupCacheKey);
        }
        
        // 清除通用配置缓存（无机器人和分组UUID的配置）
        String generalCacheKey = CACHE_KEY_AVAILABLE_PREFIX + "general";
        redisTemplate.delete(generalCacheKey);
    }
}




