package com.erp.tenant.service.feature;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.erp.common.core.exception.BusinessException;
import com.erp.tenant.entity.feature.FeatureFlag;
import com.erp.tenant.repository.feature.FeatureFlagRepository;
import com.erp.tenant.service.nacos.NacosConfigService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 功能开关服务
 * 
 * 支持动态刷新：修改后自动推送到Redis和Nacos，各服务监听变化实时更新本地缓存。
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class FeatureFlagService {

    private static final String FEATURE_CACHE_PREFIX = "feature:tenant:";
    private static final String FEATURE_ALL_KEY = "feature:all:enabled";

    private final FeatureFlagRepository featureFlagRepository;

    @Lazy
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Lazy
    @Autowired
    private NacosConfigService nacosConfigService;

    /**
     * 分页查询功能开关
     */
    public IPage<FeatureFlag> listFeatureFlags(Integer page, Integer pageSize, Long tenantId, Long packageId) {
        Page<FeatureFlag> pageParam = new Page<>(page, pageSize);
        // 使用通用查询，内存过滤
        List<FeatureFlag> all = featureFlagRepository.selectList(null);
        List<FeatureFlag> filtered = all.stream()
                .filter(f -> tenantId == null || tenantId.equals(f.getTenantId()))
                .filter(f -> packageId == null || packageId.equals(f.getPackageId()))
                .collect(Collectors.toList());

        int start = (page - 1) * pageSize;
        int end = Math.min(start + pageSize, filtered.size());
        Page<FeatureFlag> result = new Page<>(page, pageSize);
        result.setTotal(filtered.size());
        if (start < filtered.size()) {
            result.setRecords(filtered.subList(start, end));
        } else {
            result.setRecords(List.of());
        }
        return result;
    }

    /**
     * 获取租户的功能开关配置
     * 
     * @param tenantId 租户ID
     * @return 功能开关Map（key=功能键, value=是否启用）
     */
    public Map<String, Boolean> getTenantFeatures(Long tenantId) {
        String cacheKey = FEATURE_CACHE_PREFIX + tenantId;

        @SuppressWarnings("unchecked")
        Map<String, Boolean> cached = (Map<String, Boolean>) redisTemplate.opsForValue().get(cacheKey);
        if (cached != null) {
            return cached;
        }

        List<FeatureFlag> flags = featureFlagRepository.findByTenantId(tenantId);
        Map<String, Boolean> result = new HashMap<>();

        for (FeatureFlag flag : flags) {
            // 租户级别优先于全局
            if (!result.containsKey(flag.getFeatureKey())) {
                result.put(flag.getFeatureKey(), Boolean.TRUE.equals(flag.getEnabled()));
            }
        }

        // 缓存5分钟
        redisTemplate.opsForValue().set(cacheKey, result, 5, TimeUnit.MINUTES);
        return result;
    }

    /**
     * 检查租户是否启用某个功能
     */
    public boolean isFeatureEnabled(Long tenantId, String featureKey) {
        Map<String, Boolean> features = getTenantFeatures(tenantId);
        return Boolean.TRUE.equals(features.get(featureKey));
    }

    /**
     * 创建功能开关
     */
    @Transactional(rollbackFor = Exception.class)
    public FeatureFlag createFeatureFlag(FeatureFlag flag) {
        // 检查功能键唯一性
        FeatureFlag existing = featureFlagRepository.findByFeatureKey(flag.getFeatureKey());
        if (existing != null) {
            throw new BusinessException(400, "功能键已存在: " + flag.getFeatureKey());
        }

        featureFlagRepository.insert(flag);
        refreshFeatureCache(flag.getTenantId());
        pushFeatureToNacos(flag);

        log.info("创建功能开关: key={}, tenantId={}, enabled={}",
                flag.getFeatureKey(), flag.getTenantId(), flag.getEnabled());

        return flag;
    }

    /**
     * 更新功能开关
     */
    @Transactional(rollbackFor = Exception.class)
    public FeatureFlag updateFeatureFlag(Long id, Boolean enabled, String description, Integer sort) {
        FeatureFlag flag = featureFlagRepository.selectById(id);
        if (flag == null) {
            throw new BusinessException(404, "功能开关不存在");
        }

        if (enabled != null) {
            flag.setEnabled(enabled);
        }
        if (description != null) {
            flag.setDescription(description);
        }
        if (sort != null) {
            flag.setSort(sort);
        }

        featureFlagRepository.updateById(flag);
        refreshFeatureCache(flag.getTenantId());
        pushFeatureToNacos(flag);

        log.info("更新功能开关: id={}, key={}, enabled={}",
                id, flag.getFeatureKey(), flag.getEnabled());

        return flag;
    }

    /**
     * 切换功能开关状态（动态刷新）
     */
    @Transactional(rollbackFor = Exception.class)
    public FeatureFlag toggleFeatureFlag(Long id) {
        FeatureFlag flag = featureFlagRepository.selectById(id);
        if (flag == null) {
            throw new BusinessException(404, "功能开关不存在");
        }

        flag.setEnabled(!Boolean.TRUE.equals(flag.getEnabled()));
        flag.setUpdatedAt(LocalDateTime.now());
        featureFlagRepository.updateById(flag);

        // ===== 动态刷新：推送到Redis和Nacos =====
        refreshFeatureCache(flag.getTenantId());
        pushFeatureToNacos(flag);

        log.info("切换功能开关状态: id={}, key={}, newEnabled={}",
                id, flag.getFeatureKey(), flag.getEnabled());

        return flag;
    }

    /**
     * 删除功能开关
     */
    @Transactional(rollbackFor = Exception.class)
    public void deleteFeatureFlag(Long id) {
        FeatureFlag flag = featureFlagRepository.selectById(id);
        if (flag == null) {
            throw new BusinessException(404, "功能开关不存在");
        }

        featureFlagRepository.deleteById(id);
        refreshFeatureCache(flag.getTenantId());

        log.info("删除功能开关: id={}, key={}", id, flag.getFeatureKey());
    }

    /**
     * 刷新租户的功能开关缓存
     */
    private void refreshFeatureCache(Long tenantId) {
        if (tenantId == null) {
            // 刷新所有租户的缓存
            redisTemplate.delete(redisTemplate.keys(FEATURE_CACHE_PREFIX + "*"));
        } else {
            redisTemplate.delete(FEATURE_CACHE_PREFIX + tenantId);
        }
    }

    /**
     * 推送功能开关到Nacos（实现动态下发）
     */
    private void pushFeatureToNacos(FeatureFlag flag) {
        try {
            if (nacosConfigService == null) {
                log.warn("NacosConfigService未初始化，跳过推送");
                return;
            }

            Long tenantId = flag.getTenantId() != null ? flag.getTenantId() : 0L;
            nacosConfigService.publishFeatureFlag(tenantId, flag.getFeatureKey(),
                    Boolean.TRUE.equals(flag.getEnabled()));

            log.info("功能开关已推送Nacos: tenantId={}, key={}, enabled={}",
                    tenantId, flag.getFeatureKey(), flag.getEnabled());
        } catch (Exception e) {
            log.error("推送功能开关到Nacos失败: id={}, error={}", flag.getId(), e.getMessage());
        }
    }

    /**
     * 手动刷新所有租户的功能开关缓存
     */
    public void refreshAllCaches() {
        refreshFeatureCache(null);
        log.info("已刷新所有租户的功能开关缓存");
    }
}
