package com.ecep.contract.ds.project.service;

import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheConfig;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.ecep.contract.IEntityService;
import com.ecep.contract.ProjectFileType;
import com.ecep.contract.QueryService;
import com.ecep.contract.ds.project.repository.ProjectFileRepository;
import com.ecep.contract.ds.project.model.Project;
import com.ecep.contract.ds.project.model.ProjectFile;
import com.ecep.contract.service.VoableService;
import com.ecep.contract.util.SpecificationUtils;
import com.ecep.contract.vo.ProjectFileVo;
import com.fasterxml.jackson.databind.JsonNode;

@Lazy
@Service
@CacheConfig(cacheNames = "project-file")
public class ProjectFileService implements IEntityService<ProjectFile>, QueryService<ProjectFileVo>, VoableService<ProjectFile, ProjectFileVo> {
    @Lazy
    @Autowired
    private ProjectFileRepository repository;
    
    @Lazy
    @Autowired
    private ProjectService projectService;

    @Override
    public ProjectFile getById(Integer id) {
        return repository.findById(id).orElse(null);
    }

    @Cacheable(key = "#p0")
    @Override
    public ProjectFileVo findById(Integer id) {
        ProjectFile file = getById(id);
        if (file != null) {
            return file.toVo();
        }
        return null;
    }

    @Override
    public Page<ProjectFileVo> findAll(JsonNode paramsNode, Pageable pageable) {
        // 构建查询规范
        Specification<ProjectFile> spec = getSpecification(paramsNode);
        // 查询实体列表
        Page<ProjectFile> entityPage = findAll(spec, pageable);
        // 转换为VO列表
        return entityPage.map(ProjectFile::toVo);
    }

    @Override
    public Page<ProjectFile> findAll(Specification<ProjectFile> spec, Pageable pageable) {
        return repository.findAll(spec, pageable);
    }

    @Override
    public Specification<ProjectFile> getSpecification(String searchText) {
        if (!StringUtils.hasText(searchText)) {
            return null;
        }
        return (root, query, builder) -> {
            return builder.like(root.get("filePath"), "%" + searchText + "%");
        };
    }

    @Override
    public List<ProjectFile> search(String searchText) {
        Specification<ProjectFile> spec = getSpecification(searchText);
        return repository.findAll(spec);
    }

    @Override
    public void delete(ProjectFile entity) {
        repository.delete(entity);
    }

    @Override
    public ProjectFile save(ProjectFile entity) {
        return repository.save(entity);
    }

    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
    })
    public ProjectFile saveFile(ProjectFile file) {
        return repository.save(file);
    }

    @Caching(evict = {
            @CacheEvict(key = "#p0.id"),
    })
    public void deleteFile(ProjectFile file) {
        repository.delete(file);
    }

    // 根据项目查询文件列表
    public List<ProjectFileVo> findByProject(Project project) {
        List<ProjectFile> files = repository.findByProject(project);
        return files.stream().map(ProjectFile::toVo).collect(Collectors.toList());
    }

    // 根据项目和类型查询文件列表
    public List<ProjectFileVo> findByProjectAndType(Project project, ProjectFileType type) {
        List<ProjectFile> files = repository.findByProjectAndType(project, type);
        return files.stream().map(ProjectFile::toVo).collect(Collectors.toList());
    }

    // 构建查询规范
    private Specification<ProjectFile> getSpecification(JsonNode paramsNode) {
        Specification<ProjectFile> spec = null;

        // 根据参数构建查询条件
        spec = SpecificationUtils.andFieldEqualParam(spec, paramsNode, "id");
        spec = SpecificationUtils.andFieldEqualParam(spec, paramsNode, "projectId");
        spec = SpecificationUtils.andFieldEqualParam(spec, paramsNode, "type");
        
        return spec;
    }

    // 计数方法实现
    @Override
    public long count(JsonNode paramsNode) {
        Specification<ProjectFile> spec = getSpecification(paramsNode);
        if (spec != null) {
            return repository.count(spec);
        }
        return repository.count();
    }
    
    @Override
    public void updateByVo(ProjectFile model, ProjectFileVo vo) {
        // 更新文件类型
        model.setType(vo.getType());
        // 更新文件路径
        model.setFilePath(vo.getFilePath());
        // 更新项目关联
        if (vo.getProjectId() != null) {
            
            model.setProject(projectService.getById(vo.getProjectId()));
        } else {
            model.setProject(null);
        }
    }
}
