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.CreateProjectRequest;
import com.lingyue.extract.dto.request.UpdateProjectRequest;
import com.lingyue.extract.dto.response.ProjectDetailResponse;
import com.lingyue.extract.dto.response.ProjectListResponse;
import com.lingyue.extract.dto.response.SourceDocumentResponse;
import com.lingyue.extract.entity.Project;
import com.lingyue.extract.repository.ExtractResultRepository;
import com.lingyue.extract.repository.ExtractRuleRepository;
import com.lingyue.extract.repository.ProjectRepository;
import com.lingyue.extract.repository.SourceDocumentRepository;
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.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * 项目服务
 * 
 * @author lingyue
 * @since 2026-01-22
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class ProjectService {
    
    private final ProjectRepository projectRepository;
    private final SourceDocumentRepository sourceDocumentRepository;
    private final ExtractRuleRepository extractRuleRepository;
    private final ExtractResultRepository extractResultRepository;
    
    /**
     * 创建项目
     */
    @Transactional
    public Project create(String userId, CreateProjectRequest request) {
        Project project = new Project();
        project.setId(UUID.randomUUID().toString());
        project.setUserId(userId);
        project.setName(request.getName());
        project.setDescription(request.getDescription());
        project.setStatus(Project.STATUS_DRAFT);
        project.setConfig(request.getConfig());
        project.setCreateTime(new Date());
        project.setCreateBy(userId);
        
        projectRepository.insert(project);
        log.info("创建项目成功: projectId={}, name={}", project.getId(), project.getName());
        return project;
    }
    
    /**
     * 获取项目详情
     */
    public Project getById(String id) {
        return projectRepository.selectById(id);
    }
    
    /**
     * 获取项目详情（含统计信息）
     */
    public ProjectDetailResponse getProjectDetail(String id) {
        Project project = projectRepository.selectById(id);
        if (project == null) {
            return null;
        }
        
        ProjectDetailResponse response = ProjectDetailResponse.fromEntity(project);
        
        // 统计来源文档数量
        int docCount = sourceDocumentRepository.countByProjectId(id);
        response.setDocumentCount(docCount);
        
        // 统计规则数量
        int ruleCount = extractRuleRepository.countByProjectId(id);
        response.setRuleCount(ruleCount);
        
        // 统计已完成规则数量
        List<Map<String, Object>> statusCounts = extractRuleRepository.countByProjectIdGroupByStatus(id);
        int completedCount = 0;
        for (Map<String, Object> item : statusCounts) {
            String status = (String) item.get("status");
            if ("extracted".equals(status) || "confirmed".equals(status)) {
                completedCount += ((Number) item.get("count")).intValue();
            }
        }
        response.setCompletedRuleCount(completedCount);
        
        return response;
    }
    
    /**
     * 获取项目详情（含来源文档列表）
     */
    public ProjectDetailResponse getProjectWithDocuments(String id, SourceDocumentService sourceDocumentService) {
        ProjectDetailResponse response = getProjectDetail(id);
        if (response == null) {
            return null;
        }
        
        // 获取来源文档列表
        List<SourceDocumentResponse> docs = sourceDocumentService.listByProjectId(id);
        response.setSourceDocuments(docs);
        
        return response;
    }
    
    /**
     * 分页查询用户的项目
     */
    public Page<ProjectListResponse> listByUserId(String userId, int pageNum, int pageSize) {
        Page<Project> page = new Page<>(pageNum, pageSize);
        
        LambdaQueryWrapper<Project> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Project::getUserId, userId)
               .orderByDesc(Project::getCreateTime);
        
        Page<Project> resultPage = projectRepository.selectPage(page, wrapper);
        
        // 转换为响应对象
        Page<ProjectListResponse> responsePage = new Page<>();
        responsePage.setCurrent(resultPage.getCurrent());
        responsePage.setSize(resultPage.getSize());
        responsePage.setTotal(resultPage.getTotal());
        responsePage.setPages(resultPage.getPages());
        
        List<ProjectListResponse> records = resultPage.getRecords().stream()
                .map(project -> {
                    ProjectListResponse resp = ProjectListResponse.fromEntity(project);
                    // 统计来源文档和规则数量
                    resp.setDocumentCount(sourceDocumentRepository.countByProjectId(project.getId()));
                    resp.setRuleCount(extractRuleRepository.countByProjectId(project.getId()));
                    // 计算进度
                    resp.setProgress(calculateProgress(project.getId()));
                    return resp;
                })
                .collect(Collectors.toList());
        responsePage.setRecords(records);
        
        return responsePage;
    }
    
    /**
     * 按状态查询用户的项目
     */
    public List<ProjectListResponse> listByUserIdAndStatus(String userId, String status) {
        List<Project> projects = projectRepository.findByUserIdAndStatus(userId, status);
        return projects.stream()
                .map(ProjectListResponse::fromEntity)
                .collect(Collectors.toList());
    }
    
    /**
     * 更新项目
     */
    @Transactional
    public Project update(String id, UpdateProjectRequest request, String operatorId) {
        Project project = projectRepository.selectById(id);
        if (project == null) {
            return null;
        }
        
        if (request.getName() != null) {
            project.setName(request.getName());
        }
        if (request.getDescription() != null) {
            project.setDescription(request.getDescription());
        }
        if (request.getStatus() != null) {
            project.setStatus(request.getStatus());
        }
        if (request.getConfig() != null) {
            project.setConfig(request.getConfig());
        }
        
        project.setUpdateTime(new Date());
        project.setUpdateBy(operatorId);
        
        projectRepository.updateById(project);
        log.info("更新项目成功: projectId={}", id);
        return project;
    }
    
    /**
     * 删除项目（级联删除关联数据）
     */
    @Transactional
    public boolean delete(String id) {
        Project project = projectRepository.selectById(id);
        if (project == null) {
            return false;
        }
        
        log.info("开始删除项目及关联数据: projectId={}", id);
        
        // 1. 删除提取结果
        int resultCount = extractResultRepository.deleteByProjectId(id);
        log.debug("删除提取结果: {} 条", resultCount);
        
        // 2. 删除提取规则
        int ruleCount = extractRuleRepository.deleteByProjectId(id);
        log.debug("删除提取规则: {} 条", ruleCount);
        
        // 3. 删除来源文档
        int docCount = sourceDocumentRepository.deleteByProjectId(id);
        log.debug("删除来源文档: {} 条", docCount);
        
        // 4. 删除项目
        projectRepository.deleteById(id);
        
        log.info("删除项目完成: projectId={}, 删除规则={}, 删除结果={}, 删除文档={}", 
                 id, ruleCount, resultCount, docCount);
        return true;
    }
    
    /**
     * 归档项目
     */
    @Transactional
    public Project archive(String id, String operatorId) {
        Project project = projectRepository.selectById(id);
        if (project == null) {
            return null;
        }
        
        project.setStatus(Project.STATUS_ARCHIVED);
        project.setUpdateTime(new Date());
        project.setUpdateBy(operatorId);
        
        projectRepository.updateById(project);
        log.info("归档项目成功: projectId={}", id);
        return project;
    }
    
    /**
     * 计算项目进度（百分比）
     */
    private int calculateProgress(String projectId) {
        int totalRules = extractRuleRepository.countByProjectId(projectId);
        if (totalRules == 0) {
            return 0;
        }
        
        List<Map<String, Object>> statusCounts = extractRuleRepository.countByProjectIdGroupByStatus(projectId);
        int completedCount = 0;
        for (Map<String, Object> item : statusCounts) {
            String status = (String) item.get("status");
            if ("extracted".equals(status) || "confirmed".equals(status)) {
                completedCount += ((Number) item.get("count")).intValue();
            }
        }
        
        return (int) Math.round((double) completedCount / totalRules * 100);
    }
    
    /**
     * 检查用户是否有权访问项目
     */
    public boolean hasAccess(String projectId, String userId) {
        Project project = projectRepository.selectById(projectId);
        return project != null && project.getUserId().equals(userId);
    }
    
    /**
     * 获取用户项目统计
     */
    public Map<String, Integer> getProjectStatistics(String userId) {
        List<Map<String, Object>> counts = projectRepository.countByUserIdGroupByStatus(userId);
        return counts.stream()
                .collect(Collectors.toMap(
                        m -> (String) m.get("status"),
                        m -> ((Number) m.get("count")).intValue()
                ));
    }
}
