package com.keyware.shandan.browser.service;

import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.keyware.shandan.bianmu.entity.DirectoryResource;
import com.keyware.shandan.bianmu.entity.DirectoryVo;
import com.keyware.shandan.bianmu.enums.DirectoryType;
import com.keyware.shandan.bianmu.enums.ReviewStatus;
import com.keyware.shandan.bianmu.mapper.DirectoryResourceMapper;
import com.keyware.shandan.bianmu.service.DirectoryService;
import com.keyware.shandan.browser.entity.PageVo;
import com.keyware.shandan.browser.entity.SearchConditionVo;
import com.keyware.shandan.browser.entity.SearchResultSort;
import com.keyware.shandan.common.util.StreamUtil;
import com.keyware.shandan.common.util.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Service
public class MetadataSearchService {

    @Autowired
    private DirectoryService directoryService;

    @Autowired
    private DirectoryResourceMapper directoryResourceMapper;

    public PageVo<DirectoryResource> searchByCondition(String directoryId, SearchConditionVo condition) {
        QueryWrapper<DirectoryResource> queryWrapper = buildQueryWrapper(directoryId, condition);
        return PageVo.pageConvert(directoryResourceMapper.selectPage(new Page<>(condition.getPage(), condition.getSize()), queryWrapper));
    }

    public List<DirectoryResource> searchAllListByCondition(String directoryId, SearchConditionVo condition) {
        QueryWrapper<DirectoryResource> queryWrapper = buildQueryWrapper(directoryId, condition);
        return directoryResourceMapper.selectList(queryWrapper);
    }

    public QueryWrapper<DirectoryResource> buildQueryWrapper(String directoryId, SearchConditionVo condition) {
        QueryWrapper<DirectoryResource> queryWrapper = new QueryWrapper<>();
        DirectoryVo dir = directoryService.getById(directoryId);
        Assert.notNull(dir, "资源目录未找到");

        // 查找当前目录下审核通过的下级目录
        List<String> parentIds = StreamUtil.as(getAllDirChildren(dir)).map(DirectoryVo::getId).toList();
        queryWrapper.in("PARENT_ID", parentIds);

        queryWrapper.and(condition.getConditions().size() > 0, wrapper -> {
            StreamUtil.as(condition.getConditions()).forEach(item -> {
                switch (item.getFieldName()) {
                    case "inputDate":
                        if (StringUtils.hasText(item.getFieldValue())) {
                            String[] dates = item.getFieldValue().split("至");
                            wrapper.between("TASK_TIME", dates[0].trim(), dates[1].trim());
                        }
                        break;
                    case "dataFrom":
                        if ("nq".equals(item.getLogicJudgement())) {
                            wrapper.ne("DATA_SOURCE", item.getFieldValue());
                        } else {
                            wrapper.eq("DATA_SOURCE", item.getFieldValue());
                        }
                        break;
                    case "dataType":
                        if ("nq".equals(item.getLogicJudgement())) {
                            wrapper.ne("DATA_TYPE", item.getFieldValue());
                        } else {
                            wrapper.eq("DATA_TYPE", item.getFieldValue());
                        }
                        break;
                    case "metadataName":
                        if (StringUtils.hasText(item.getFieldValue())) {
                            for (String value : item.getFieldValue().split(" ")) {
                                wrapper.and(StringUtils.hasText(value.trim()), qw -> {
                                    if ("eq".equals(item.getLogicJudgement())) {
                                        qw.eq("RESOURCE_NAME", value.trim())/*.or().eq("RESOURCE_COMMENT", value.trim())*/;
                                    }else{
                                        qw.like("RESOURCE_NAME", value.trim())/*.or().like("RESOURCE_COMMENT", value.trim())*/;
                                    }
                                });
                            }
                        }
                        break;
                    case "markTag":
                        String tagIds = item.getFieldValue();
                        List<String> ids = Arrays.asList(tagIds.split(","));
                        if (!ids.isEmpty()) {
                            StringBuilder existsSql = new StringBuilder("select 1 from (select ENTITY_ID, WM_CONCAT(LABEL_ID) LABEL_IDS from B_DATA_LABEL_ENTITY DLN where DLN.ENTITY_ID = V_DIRECTORY_RESOURCE.ID group by ENTITY_ID) tmp1");
                            List<String> andSqlList = ids.stream().map(id -> "tmp1.LABEL_IDS like '%" + id + "%'").collect(Collectors.toList());
                            existsSql.append(" where ").append(String.join(" and ", andSqlList));
                            wrapper.exists(existsSql.toString());
                        }

                        break;
                    default:
                }
            });
        });

        // 排序设置
        SearchResultSort sort = condition.getSort();
        if (sort != null && sort.getSort() != null) {
            // 通过反射获取资源类字段注解中的数据库表相关的列名
            Field field = ReflectUtil.getField(DirectoryResource.class, sort.getField().trim());
            if (field != null) {
                TableField tableField = field.getAnnotation(TableField.class);
                if (tableField != null && StringUtils.hasText(tableField.value())) {
                    queryWrapper.orderBy(true, sort.getSort().equalsIgnoreCase("asc"), tableField.value());
                }
            }
        }
        return queryWrapper;
    }

    /**
     * 获取指定目录下 所有审核通过的下级目录集合
     *
     * @param parent 上级目录
     * @return 目录集合
     */
    private List<DirectoryVo> getAllDirChildren(DirectoryVo parent) {
        QueryWrapper<DirectoryVo> wrapper = new QueryWrapper<>();
        wrapper.likeRight("DIRECTORY_PATH", parent.getDirectoryPath())
                .in("DIRECTORY_TYPE", DirectoryType.DIRECTORY, DirectoryType.LINK_DIR)
                .in("REVIEW_STATUS", ReviewStatus.PASS, ReviewStatus.SUBMITTED);
        return directoryService.list(wrapper);
    }
}
