package com.lingyue.extract.service;

import com.lingyue.extract.dto.request.AddVariableRequest;
import com.lingyue.extract.entity.Variable;
import com.lingyue.extract.repository.VariableRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 变量服务
 * 
 * @author lingyue
 * @since 2026-01-23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class VariableService {
    
    private final VariableRepository variableRepository;
    private final ExtractionService extractionService;
    
    /**
     * 添加变量
     */
    @Transactional
    public Variable add(String templateId, AddVariableRequest request) {
        // 检查变量名是否重复
        Variable existing = variableRepository.findByTemplateIdAndName(templateId, request.getName());
        if (existing != null) {
            throw new RuntimeException("变量名已存在: " + request.getName());
        }
        
        Variable variable = new Variable();
        variable.setId(UUID.randomUUID().toString().replace("-", ""));
        variable.setTemplateId(templateId);
        variable.setName(request.getName());
        variable.setDisplayName(request.getDisplayName());
        variable.setVariableGroup(request.getVariableGroup());
        variable.setCategory(request.getCategory());
        variable.setLocation(request.getLocation());
        variable.setExampleValue(request.getExampleValue());
        variable.setValueType(request.getValueType() != null ? request.getValueType() : Variable.VALUE_TYPE_TEXT);
        variable.setSourceFileAlias(request.getSourceFileAlias());
        variable.setSourceType(request.getSourceType());
        variable.setSourceConfig(request.getSourceConfig());
        variable.setExtractType(request.getExtractType());
        variable.setExtractConfig(request.getExtractConfig());
        
        // 设置显示顺序
        int maxOrder = variableRepository.getMaxDisplayOrder(templateId);
        variable.setDisplayOrder(maxOrder + 1);
        variable.setCreateTime(new Date());
        variable.setUpdateTime(new Date());
        
        variableRepository.insert(variable);
        log.info("添加变量成功: templateId={}, name={}", templateId, request.getName());
        
        return variable;
    }
    
    /**
     * 批量添加变量
     */
    @Transactional
    public List<Variable> batchAdd(String templateId, List<AddVariableRequest> requests) {
        return requests.stream()
                .map(request -> add(templateId, request))
                .toList();
    }
    
    /**
     * 根据ID获取
     */
    public Variable getById(String id) {
        return variableRepository.selectById(id);
    }
    
    /**
     * 根据变量名获取
     */
    public Variable getByName(String templateId, String name) {
        return variableRepository.findByTemplateIdAndName(templateId, name);
    }
    
    /**
     * 获取模板的所有变量
     */
    public List<Variable> listByTemplateId(String templateId) {
        return variableRepository.findByTemplateId(templateId);
    }
    
    /**
     * 按来源文件别名获取变量
     */
    public List<Variable> listBySourceFileAlias(String templateId, String alias) {
        return variableRepository.findByTemplateIdAndSourceFileAlias(templateId, alias);
    }
    
    /**
     * 按来源类型获取变量
     */
    public List<Variable> listBySourceType(String templateId, String sourceType) {
        return variableRepository.findByTemplateIdAndSourceType(templateId, sourceType);
    }
    
    /**
     * 按分组获取变量
     */
    public List<Variable> listByGroup(String templateId, String group) {
        return variableRepository.findByTemplateIdAndGroup(templateId, group);
    }
    
    /**
     * 按类别获取变量
     */
    public List<Variable> listByCategory(String templateId, String category) {
        return variableRepository.findByTemplateIdAndCategory(templateId, category);
    }
    
    /**
     * 获取变量按类别分组
     * 返回 Map<category, List<Variable>>
     */
    public java.util.Map<String, List<Variable>> listGroupedByCategory(String templateId) {
        List<Variable> variables = variableRepository.findByTemplateId(templateId);
        return variables.stream()
                .collect(java.util.stream.Collectors.groupingBy(
                        v -> v.getCategory() != null ? v.getCategory() : "other"
                ));
    }
    
    /**
     * 更新变量
     */
    @Transactional
    public Variable update(String id, AddVariableRequest request) {
        Variable variable = variableRepository.selectById(id);
        if (variable == null) {
            return null;
        }
        
        // 检查变量名是否重复（排除自己）
        if (request.getName() != null && !request.getName().equals(variable.getName())) {
            Variable existing = variableRepository.findByTemplateIdAndName(variable.getTemplateId(), request.getName());
            if (existing != null) {
                throw new RuntimeException("变量名已存在: " + request.getName());
            }
            variable.setName(request.getName());
        }
        
        if (request.getDisplayName() != null) {
            variable.setDisplayName(request.getDisplayName());
        }
        if (request.getVariableGroup() != null) {
            variable.setVariableGroup(request.getVariableGroup());
        }
        if (request.getCategory() != null) {
            variable.setCategory(request.getCategory());
        }
        if (request.getLocation() != null) {
            variable.setLocation(request.getLocation());
        }
        if (request.getExampleValue() != null) {
            variable.setExampleValue(request.getExampleValue());
        }
        if (request.getValueType() != null) {
            variable.setValueType(request.getValueType());
        }
        if (request.getSourceFileAlias() != null) {
            variable.setSourceFileAlias(request.getSourceFileAlias());
        }
        if (request.getSourceType() != null) {
            variable.setSourceType(request.getSourceType());
        }
        if (request.getSourceConfig() != null) {
            variable.setSourceConfig(request.getSourceConfig());
        }
        if (request.getExtractType() != null) {
            variable.setExtractType(request.getExtractType());
        }
        if (request.getExtractConfig() != null) {
            variable.setExtractConfig(request.getExtractConfig());
        }
        
        variable.setUpdateTime(new Date());
        variableRepository.updateById(variable);
        log.info("更新变量成功: id={}", id);
        
        return variable;
    }
    
    /**
     * 删除变量
     */
    @Transactional
    public boolean delete(String id) {
        Variable variable = variableRepository.selectById(id);
        if (variable == null) {
            return false;
        }
        
        // 检查是否有其他变量引用此变量
        List<Variable> referencing = variableRepository.findVariablesReferencingVariable(
                variable.getTemplateId(), variable.getName());
        if (!referencing.isEmpty()) {
            throw new RuntimeException("变量被 " + referencing.size() + " 个其他变量引用，无法删除");
        }
        
        variableRepository.deleteById(id);
        log.info("删除变量成功: id={}", id);
        
        return true;
    }
    
    /**
     * 强制删除（忽略引用检查）
     */
    @Transactional
    public boolean forceDelete(String id) {
        Variable variable = variableRepository.selectById(id);
        if (variable == null) {
            return false;
        }
        
        variableRepository.deleteById(id);
        log.info("强制删除变量成功: id={}", id);
        
        return true;
    }
    
    /**
     * 统计数量
     */
    public int count(String templateId) {
        return variableRepository.countByTemplateId(templateId);
    }
    
    /**
     * 获取引用指定变量的变量列表
     */
    public List<Variable> findReferencingVariables(String templateId, String variableName) {
        return variableRepository.findVariablesReferencingVariable(templateId, variableName);
    }
    
    /**
     * 重排序变量
     */
    @Transactional
    public void reorder(String templateId, List<String> orderedIds) {
        List<Variable> variables = variableRepository.findByTemplateId(templateId);
        
        // 验证所有ID都存在
        for (String id : orderedIds) {
            boolean found = variables.stream().anyMatch(v -> v.getId().equals(id));
            if (!found) {
                throw new RuntimeException("变量不存在: " + id);
            }
        }
        
        // 更新顺序
        for (int i = 0; i < orderedIds.size(); i++) {
            String id = orderedIds.get(i);
            Variable v = variables.stream()
                    .filter(var -> var.getId().equals(id))
                    .findFirst()
                    .orElse(null);
            if (v != null && v.getDisplayOrder() != i) {
                v.setDisplayOrder(i);
                v.setUpdateTime(new Date());
                variableRepository.updateById(v);
            }
        }
        
        log.info("重排序变量成功: templateId={}, count={}", templateId, orderedIds.size());
    }
    
    /**
     * 预览提取结果（使用示例文档测试提取配置）
     * 预览提取结果（使用示例文档测试提取配置）
     */
    public com.lingyue.extract.dto.response.VariablePreviewResponse preview(String variableId, String documentId) {
        return extractionService.previewExtract(variableId, documentId);
    }
}
