package com.keyware.shandan.browser.controller;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
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.MetadataBasicVo;
import com.keyware.shandan.bianmu.service.MetadataService;
import com.keyware.shandan.browser.entity.FullSearchParam;
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.browser.service.*;
import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.common.util.FileDownload;
import com.keyware.shandan.common.util.UUIDUtil;
import com.keyware.shandan.frame.annotation.AppLog;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 组合搜索前端控制器
 *
 * @author Administrator
 * @since 2021/7/1
 */
@RestController
@RequestMapping("/search")
public class SearchController {

    @Autowired
    private SearchService searchService;

    @Autowired
    private MetadataService metadataService;

    @Autowired
    private MetadataDataService metadataDataService;

    @Autowired
    private FileSearchService fileSearchService;

    @Autowired
    private MetadataSearchService metadataSearchService;

    private final Map<String, ExportComponent> exportCache = new HashMap<>();

    /**
     * 全文检索分页查询
     *
     * @param condition 条件
     * @return -
     */
    @AppLog(operate = "全文检索分页查询")
    @PostMapping("/full")
    public Result<PageVo> fullSearch(SearchConditionVo condition) {

        try {
            return Result.of(searchService.esSearch(condition));
        } catch (IOException e) {
            e.printStackTrace();
            return Result.of(null, false, "数据查询异常");
        }
    }


    /**
     * 测试接口
     *
     * @param condition
     * @return
     */
    @PostMapping("/full/test")
    public Result<PageVo> fullSearchTest(@RequestBody SearchConditionVo condition) {

        try {
            return Result.of(searchService.esSearch(condition));
        } catch (IOException e) {
            e.printStackTrace();
            return Result.of(null, false, "数据查询异常");
        }
    }

    @GetMapping("/metadata/columns")
    public Result<JSONObject> getMetaColumns(String metaTable) {
        QueryWrapper<MetadataBasicVo> qw = new QueryWrapper<>();
        qw.eq("METADATA_NAME", metaTable);
        List<MetadataBasicVo> list = metadataService.list(qw);
        if (list != null && list.size() > 0) {
            MetadataBasicVo basicVo = list.get(0);
            JSONObject json = (JSONObject) JSONObject.toJSON(basicVo);
            json.put("field", getFiledByMetadata(basicVo));
            return Result.of(json);
        }
        return Result.of(null, false);
    }

    /**
     * 查询指定数据资源表的分页数据
     *
     * @param metaID
     * @param page
     * @param size
     * @param orderField
     * @param order
     * @return
     */
    @PostMapping("/metadata/page")
    public Result<PageVo> dataPageByMetadata(String metaID, Integer page, Integer size, String orderField, String order) {
        MetadataBasicVo basicVo = metadataService.getById(metaID);
        if (basicVo != null) {
            Page<HashMap<String, Object>> dataList = metadataService.getDynamicData(basicVo, page, size, orderField, order);
            return Result.of(PageVo.pageConvert(dataList));
        }

        return Result.of(null, false);
    }

    private JSONArray getFiledByMetadata(MetadataBasicVo basicVo) {
        JSONArray jsonArray = new JSONArray();
        basicVo.getMetadataDetailsList().forEach(detail -> {
            jsonArray.addAll(JSONArray.parseArray(detail.getTableColumns()));
        });
        return jsonArray;
    }


    /**
     * 全文检索-检索文件
     *
     * @return 文件结果列表
     */
    @AppLog(operate = "文件全文检索查询")
    @GetMapping("/full/file")
    public Result<Object> searchFile(FullSearchParam param) {

        try {
            return Result.of(fileSearchService.searchFile(param));
        } catch (IOException e) {
            e.printStackTrace();
            return Result.of(null, false, "Elasticsearch 请求异常");
        }
    }

    /**
     * 查询指定数据资源下的数据
     *
     * @param metaId    数据资源ID
     * @param condition 条件项
     * @return 分页列表
     */
    @AppLog(operate = "查询指定数据资源下的数据")
    @PostMapping("/metadata/condition/{metaId}")
    public Result<PageVo> searchDataByMetadata(@PathVariable String metaId, SearchConditionVo condition) {
        MetadataBasicVo metadata = metadataService.get(metaId).getData();
        if (metadata != null) {
            return Result.of(metadataDataService.queryData(metadata, condition));
        }
        return Result.of(new PageVo());
    }

    @PostMapping("/metadata/condition/query")
    public Result<PageVo> searchDataByMetadataTest(@RequestParam String metaId, @RequestBody SearchConditionVo condition) {
        MetadataBasicVo metadata = metadataService.get(metaId).getData();
        if (metadata != null) {
            return Result.of(metadataDataService.queryData(metadata, condition));
        }
        return Result.of(new PageVo());
    }

    @GetMapping("/metadata/condition/get")
    public Result<PageVo> searchDataByMetadata2(@RequestParam String metaId,
                                                @RequestParam(value = "page", defaultValue = "1") int page,
                                                @RequestParam(value = "size", defaultValue = "10") int size) {
        SearchConditionVo condition = new SearchConditionVo();
        condition.setSize(size);
        condition.setPage(page);
        MetadataBasicVo metadata = metadataService.get(metaId).getData();
        if (metadata != null) {
            return Result.of(metadataDataService.queryData(metadata, condition));
        }
        return Result.of(new PageVo());
    }

    @PostMapping("/metadata/all/page/{directoryId}")
    public Result<Object> searchMetadataPage(@PathVariable String directoryId, SearchConditionVo condition) {
        return Result.of(metadataSearchService.searchByCondition(directoryId, condition));
    }

    /**
     * 数据导出-查询数据
     *
     * @param directoryId  目录ID
     * @param metadataName 资源模糊查询
     * @param condition    复杂查询条件
     * @return 导出ID
     */
    @PostMapping("/export/query/{directoryId}")
    public Result<Object> exportQuery(@PathVariable String directoryId, String metadataName, SearchConditionVo condition) {
        String exportId = UUIDUtil.getUUID();
        ExportComponent exportComponent = new ExportComponent(exportId);

        List<DirectoryResource> list = metadataSearchService.searchAllListByCondition(directoryId, condition);
        exportComponent.setData(list);
        exportCache.put(exportId, exportComponent);

        Map<String, String> result = new HashMap<>();
        result.put("exportId", exportId);
        return Result.of(result);
    }

    /**
     * 数据导出-打包数据
     *
     * @param exportId 导出ID
     * @return 导出ID
     */
    @GetMapping("/export/package/{exportId}")
    public Result<Object> exportPackage(@PathVariable String exportId) {
        ExportComponent exportComponent = exportCache.get(exportId);
        boolean flag = exportComponent.startPackage();

        Map<String, String> result = new HashMap<>();
        result.put("exportId", exportId);
        return Result.of(result, flag);
    }

    /**
     * 数据导出-下载
     *
     * @param response HttpServletResponse
     * @param exportId 导出ID
     * @return -
     */
    @GetMapping("/export/download/{exportId}")
    public String exportDownload(HttpServletResponse response, @PathVariable String exportId) {
        String path = exportCache.remove(exportId).getExportPath() + ".zip";
        String downloadName = FileUtil.getName(path);
        File file = new File(path);
        return FileDownload.download(response, file, downloadName);
    }

}
