package com.lingyue.extract.service;

import com.lingyue.extract.dto.request.AddSourceFileRequest;
import com.lingyue.extract.entity.SourceFile;
import com.lingyue.extract.entity.Variable;
import com.lingyue.extract.repository.SourceFileRepository;
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.Arrays;
import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * 来源文件定义服务
 * 
 * @author lingyue
 * @since 2026-01-23
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SourceFileService {
    
    private final SourceFileRepository sourceFileRepository;
    private final VariableRepository variableRepository;
    
    /**
     * 添加来源文件定义
     */
    @Transactional
    public SourceFile add(String templateId, AddSourceFileRequest request) {
        // 检查别名是否重复
        SourceFile existing = sourceFileRepository.findByTemplateIdAndAlias(templateId, request.getAlias());
        if (existing != null) {
            throw new RuntimeException("来源文件别名已存在: " + request.getAlias());
        }
        
        SourceFile sourceFile = new SourceFile();
        sourceFile.setId(UUID.randomUUID().toString().replace("-", ""));
        sourceFile.setTemplateId(templateId);
        sourceFile.setAlias(request.getAlias());
        sourceFile.setDescription(request.getDescription());
        sourceFile.setFileTypes(request.getFileTypes() != null ? request.getFileTypes() : Arrays.asList("pdf", "docx"));
        sourceFile.setRequired(request.getRequired() != null ? request.getRequired() : true);
        sourceFile.setExampleDocumentId(request.getExampleDocumentId());
        
        // 设置显示顺序
        int maxOrder = sourceFileRepository.getMaxDisplayOrder(templateId);
        sourceFile.setDisplayOrder(maxOrder + 1);
        sourceFile.setCreateTime(new Date());
        
        sourceFileRepository.insert(sourceFile);
        log.info("添加来源文件定义成功: templateId={}, alias={}", templateId, request.getAlias());
        
        return sourceFile;
    }
    
    /**
     * 批量添加来源文件定义
     */
    @Transactional
    public List<SourceFile> batchAdd(String templateId, List<AddSourceFileRequest> requests) {
        return requests.stream()
                .map(request -> add(templateId, request))
                .toList();
    }
    
    /**
     * 根据ID获取
     */
    public SourceFile getById(String id) {
        return sourceFileRepository.selectById(id);
    }
    
    /**
     * 获取模板的所有来源文件定义
     */
    public List<SourceFile> listByTemplateId(String templateId) {
        return sourceFileRepository.findByTemplateId(templateId);
    }
    
    /**
     * 根据别名获取
     */
    public SourceFile getByAlias(String templateId, String alias) {
        return sourceFileRepository.findByTemplateIdAndAlias(templateId, alias);
    }
    
    /**
     * 更新来源文件定义
     */
    @Transactional
    public SourceFile update(String id, AddSourceFileRequest request) {
        SourceFile sourceFile = sourceFileRepository.selectById(id);
        if (sourceFile == null) {
            return null;
        }
        
        // 检查别名是否重复（排除自己）
        if (request.getAlias() != null && !request.getAlias().equals(sourceFile.getAlias())) {
            SourceFile existing = sourceFileRepository.findByTemplateIdAndAlias(sourceFile.getTemplateId(), request.getAlias());
            if (existing != null) {
                throw new RuntimeException("来源文件别名已存在: " + request.getAlias());
            }
            
            // 更新关联变量的别名
            List<Variable> variables = variableRepository.findByTemplateIdAndSourceFileAlias(
                    sourceFile.getTemplateId(), sourceFile.getAlias());
            for (Variable v : variables) {
                v.setSourceFileAlias(request.getAlias());
                v.setUpdateTime(new Date());
                variableRepository.updateById(v);
            }
            
            sourceFile.setAlias(request.getAlias());
        }
        
        if (request.getDescription() != null) {
            sourceFile.setDescription(request.getDescription());
        }
        if (request.getFileTypes() != null) {
            sourceFile.setFileTypes(request.getFileTypes());
        }
        if (request.getRequired() != null) {
            sourceFile.setRequired(request.getRequired());
        }
        if (request.getExampleDocumentId() != null) {
            sourceFile.setExampleDocumentId(request.getExampleDocumentId());
        }
        
        sourceFileRepository.updateById(sourceFile);
        log.info("更新来源文件定义成功: id={}", id);
        
        return sourceFile;
    }
    
    /**
     * 删除来源文件定义
     */
    @Transactional
    public boolean delete(String id) {
        SourceFile sourceFile = sourceFileRepository.selectById(id);
        if (sourceFile == null) {
            return false;
        }
        
        // 检查是否有变量引用
        List<Variable> variables = variableRepository.findByTemplateIdAndSourceFileAlias(
                sourceFile.getTemplateId(), sourceFile.getAlias());
        if (!variables.isEmpty()) {
            throw new RuntimeException("来源文件被 " + variables.size() + " 个变量引用，无法删除");
        }
        
        sourceFileRepository.deleteById(id);
        log.info("删除来源文件定义成功: id={}", id);
        
        return true;
    }
    
    /**
     * 强制删除（同时清除变量的引用）
     */
    @Transactional
    public boolean forceDelete(String id) {
        SourceFile sourceFile = sourceFileRepository.selectById(id);
        if (sourceFile == null) {
            return false;
        }
        
        // 清除变量的来源文件引用
        List<Variable> variables = variableRepository.findByTemplateIdAndSourceFileAlias(
                sourceFile.getTemplateId(), sourceFile.getAlias());
        for (Variable v : variables) {
            v.setSourceFileAlias(null);
            v.setUpdateTime(new Date());
            variableRepository.updateById(v);
        }
        
        sourceFileRepository.deleteById(id);
        log.info("强制删除来源文件定义成功: id={}, clearedVariables={}", id, variables.size());
        
        return true;
    }
    
    /**
     * 获取必须的来源文件定义
     */
    public List<SourceFile> listRequired(String templateId) {
        return sourceFileRepository.findRequiredByTemplateId(templateId);
    }
    
    /**
     * 统计数量
     */
    public int count(String templateId) {
        return sourceFileRepository.countByTemplateId(templateId);
    }
    
    /**
     * 重排序来源文件定义
     */
    @Transactional
    public void reorder(String templateId, List<String> orderedIds) {
        List<SourceFile> sourceFiles = sourceFileRepository.findByTemplateId(templateId);
        
        // 验证所有ID都存在
        for (String id : orderedIds) {
            boolean found = sourceFiles.stream().anyMatch(sf -> sf.getId().equals(id));
            if (!found) {
                throw new RuntimeException("来源文件不存在: " + id);
            }
        }
        
        // 更新顺序
        for (int i = 0; i < orderedIds.size(); i++) {
            String id = orderedIds.get(i);
            SourceFile sf = sourceFiles.stream()
                    .filter(s -> s.getId().equals(id))
                    .findFirst()
                    .orElse(null);
            if (sf != null && sf.getDisplayOrder() != i) {
                sf.setDisplayOrder(i);
                sourceFileRepository.updateById(sf);
            }
        }
        
        log.info("重排序来源文件定义成功: templateId={}, count={}", templateId, orderedIds.size());
    }
}
