package com.lingyue.extract.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.lingyue.extract.dto.request.CreateGenerationRequest;
import com.lingyue.extract.dto.request.GenerationProgressResponse;
import com.lingyue.extract.dto.response.GenerationResponse;
import com.lingyue.extract.entity.Generation;
import com.lingyue.extract.entity.SourceFile;
import com.lingyue.extract.entity.Template;
import com.lingyue.extract.entity.Variable;
import com.lingyue.extract.repository.GenerationRepository;
import com.lingyue.extract.repository.SourceFileRepository;
import com.lingyue.extract.repository.TemplateRepository;
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.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 生成任务服务
 * 
 * @author lingyue
 * @since 2026-01-24
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class GenerationService {
    
    private final GenerationRepository generationRepository;
    private final TemplateRepository templateRepository;
    private final SourceFileRepository sourceFileRepository;
    private final VariableRepository variableRepository;
    private final ExtractionService extractionService;
    private final DocumentGenerationService documentGenerationService;
    
    /**
     * 创建生成任务
     */
    @Transactional
    public Generation create(String userId, CreateGenerationRequest request) {
        // 验证模板
        Template template = templateRepository.selectById(request.getTemplateId());
        if (template == null) {
            throw new RuntimeException("模板不存在");
        }
        if (!Template.STATUS_PUBLISHED.equals(template.getStatus())) {
            throw new RuntimeException("模板未发布，无法使用");
        }
        
        // 验证来源文件
        List<SourceFile> requiredFiles = sourceFileRepository.findRequiredByTemplateId(request.getTemplateId());
        for (SourceFile sf : requiredFiles) {
            if (!request.getSourceFileMap().containsKey(sf.getAlias())) {
                throw new RuntimeException("缺少必须的来源文件: " + sf.getAlias());
            }
        }
        
        // 获取变量列表，初始化变量值
        List<Variable> variables = variableRepository.findByTemplateId(request.getTemplateId());
        Map<String, Generation.VariableValue> variableValues = new HashMap<>();
        for (Variable v : variables) {
            Generation.VariableValue vv = new Generation.VariableValue();
            vv.setVariableName(v.getName());
            vv.setDisplayName(v.getDisplayName());
            vv.setStatus(Generation.VariableValue.STATUS_PENDING);
            variableValues.put(v.getName(), vv);
        }
        
        // 创建生成任务
        Generation generation = new Generation();
        generation.setId(UUID.randomUUID().toString().replace("-", ""));
        generation.setTemplateId(request.getTemplateId());
        generation.setUserId(userId);
        generation.setName(request.getName() != null ? request.getName() : template.getName() + " - " + new Date());
        generation.setSourceFileMap(request.getSourceFileMap());
        generation.setVariableValues(variableValues);
        generation.setStatus(Generation.STATUS_PENDING);
        generation.setProgress(0);
        generation.setCreateTime(new Date());
        
        generationRepository.insert(generation);
        
        // 增加模板使用次数
        templateRepository.incrementUseCount(request.getTemplateId());
        
        log.info("创建生成任务成功: id={}, templateId={}, userId={}", 
                generation.getId(), request.getTemplateId(), userId);
        
        return generation;
    }
    
    /**
     * 根据ID获取
     */
    public Generation getById(String id) {
        return generationRepository.selectById(id);
    }
    
    /**
     * 获取任务详情（包含模板名称）
     */
    public GenerationResponse getDetail(String id) {
        Generation generation = generationRepository.selectById(id);
        if (generation == null) {
            return null;
        }
        
        GenerationResponse response = GenerationResponse.fromEntity(generation);
        
        // 填充模板名称
        Template template = templateRepository.selectById(generation.getTemplateId());
        if (template != null) {
            response.setTemplateName(template.getName());
        }
        
        return response;
    }
    
    /**
     * 分页查询用户的生成任务
     */
    public Page<GenerationResponse> listByUserId(String userId, int page, int size) {
        Page<Generation> pageRequest = new Page<>(page, size);
        
        LambdaQueryWrapper<Generation> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Generation::getUserId, userId)
               .orderByDesc(Generation::getCreateTime);
        
        Page<Generation> generationPage = generationRepository.selectPage(pageRequest, wrapper);
        
        // 转换为响应对象
        Page<GenerationResponse> responsePage = new Page<>(page, size, generationPage.getTotal());
        List<GenerationResponse> records = generationPage.getRecords().stream()
                .map(generation -> {
                    GenerationResponse response = GenerationResponse.fromEntity(generation);
                    // 填充模板名称
                    Template template = templateRepository.selectById(generation.getTemplateId());
                    if (template != null) {
                        response.setTemplateName(template.getName());
                    }
                    return response;
                })
                .collect(Collectors.toList());
        responsePage.setRecords(records);
        
        return responsePage;
    }
    
    /**
     * 按模板查询生成任务
     */
    public List<GenerationResponse> listByTemplateId(String templateId) {
        List<Generation> generations = generationRepository.findByTemplateId(templateId);
        return generations.stream()
                .map(GenerationResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    /**
     * 执行提取（异步处理，这里只更新状态）
     */
    @Transactional
    public Generation execute(String id) {
        Generation generation = generationRepository.selectById(id);
        if (generation == null) {
            throw new RuntimeException("生成任务不存在");
        }
        
        if (!Generation.STATUS_PENDING.equals(generation.getStatus()) && 
            !Generation.STATUS_ERROR.equals(generation.getStatus())) {
            throw new RuntimeException("当前状态不允许执行: " + generation.getStatus());
        }
        
        // 更新状态为提取中
        generation.setStatus(Generation.STATUS_EXTRACTING);
        generation.setProgress(0);
        generation.setErrorMessage(null);
        generationRepository.updateById(generation);
        
        // 异步执行提取（使用简单的线程池，生产环境应使用消息队列）
        final String generationId = id;
        new Thread(() -> {
            try {
                extractionService.executeExtraction(generationId);
                extractionService.processReferenceVariables(generationId);
            } catch (Exception e) {
                log.error("提取执行失败: generationId={}", generationId, e);
                Generation gen = generationRepository.selectById(generationId);
                if (gen != null) {
                    gen.setStatus(Generation.STATUS_ERROR);
                    gen.setErrorMessage(e.getMessage());
                    generationRepository.updateById(gen);
                }
            }
        }).start();
        
        log.info("开始执行生成任务: id={}", id);
        
        return generation;
    }
    
    /**
     * 获取执行进度
     */
    public GenerationProgressResponse getProgress(String id) {
        Generation generation = generationRepository.selectById(id);
        if (generation == null) {
            return null;
        }
        
        int total = 0;
        int completed = 0;
        String currentVariable = null;
        
        if (generation.getVariableValues() != null) {
            total = generation.getVariableValues().size();
            for (Generation.VariableValue vv : generation.getVariableValues().values()) {
                if (Generation.VariableValue.STATUS_EXTRACTED.equals(vv.getStatus()) || 
                    Generation.VariableValue.STATUS_MANUAL.equals(vv.getStatus())) {
                    completed++;
                } else if ("extracting".equals(vv.getStatus())) {
                    currentVariable = vv.getDisplayName();
                }
            }
        }
        
        return GenerationProgressResponse.of(
                id, 
                generation.getStatus(), 
                generation.getProgress(), 
                total, 
                completed, 
                currentVariable
        );
    }
    
    /**
     * 更新变量值
     */
    @Transactional
    public Generation updateVariableValue(String id, String variableName, String value) {
        Generation generation = generationRepository.selectById(id);
        if (generation == null) {
            throw new RuntimeException("生成任务不存在");
        }
        
        if (generation.getVariableValues() == null) {
            throw new RuntimeException("变量列表为空");
        }
        
        Generation.VariableValue vv = generation.getVariableValues().get(variableName);
        if (vv == null) {
            throw new RuntimeException("变量不存在: " + variableName);
        }
        
        vv.setValue(value);
        vv.setStatus(Generation.VariableValue.STATUS_MANUAL);
        
        generationRepository.updateById(generation);
        log.info("更新变量值成功: generationId={}, variable={}", id, variableName);
        
        return generation;
    }
    
    /**
     * 确认并生成文档
     */
    @Transactional
    public Generation confirm(String id) {
        Generation generation = generationRepository.selectById(id);
        if (generation == null) {
            throw new RuntimeException("生成任务不存在");
        }
        
        if (!Generation.STATUS_REVIEW.equals(generation.getStatus())) {
            throw new RuntimeException("当前状态不允许确认: " + generation.getStatus());
        }
        
        // 检查是否所有必须的变量都有值
        if (generation.getVariableValues() != null) {
            for (Map.Entry<String, Generation.VariableValue> entry : generation.getVariableValues().entrySet()) {
                Generation.VariableValue vv = entry.getValue();
                if (vv.getValue() == null || vv.getValue().isEmpty()) {
                    // TODO: 检查变量是否必须
                    log.warn("变量 {} 没有值", entry.getKey());
                }
            }
        }
        
        // 更新状态为生成中
        generation.setStatus(Generation.STATUS_GENERATING);
        generationRepository.updateById(generation);
        
        // 异步生成文档
        final String generationId = id;
        new Thread(() -> {
            try {
                documentGenerationService.generateDocument(generationId);
            } catch (Exception e) {
                log.error("文档生成失败: generationId={}", generationId, e);
            }
        }).start();
        
        log.info("确认生成任务，开始生成文档: id={}", id);
        
        return generation;
    }
    
    /**
     * 删除生成任务
     */
    @Transactional
    public boolean delete(String id) {
        Generation generation = generationRepository.selectById(id);
        if (generation == null) {
            return false;
        }
        
        // 不允许删除正在执行的任务
        if (Generation.STATUS_EXTRACTING.equals(generation.getStatus()) ||
            Generation.STATUS_GENERATING.equals(generation.getStatus())) {
            throw new RuntimeException("任务正在执行中，无法删除");
        }
        
        generationRepository.deleteById(id);
        log.info("删除生成任务成功: id={}", id);
        
        return true;
    }
    
    /**
     * 获取用户最近的生成任务
     */
    public List<GenerationResponse> getRecentByUserId(String userId, int limit) {
        List<Generation> generations = generationRepository.findRecentByUserId(userId, limit);
        return generations.stream()
                .map(generation -> {
                    GenerationResponse response = GenerationResponse.fromEntity(generation);
                    Template template = templateRepository.selectById(generation.getTemplateId());
                    if (template != null) {
                        response.setTemplateName(template.getName());
                    }
                    return response;
                })
                .collect(Collectors.toList());
    }
}
