package com.keyware.shandan.bianmu.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.keyware.shandan.bianmu.entity.DirectoryMetadataVo;
import com.keyware.shandan.bianmu.entity.MetadataBasicVo;
import com.keyware.shandan.bianmu.enums.ReviewStatus;
import com.keyware.shandan.bianmu.service.DataLabelsService;
import com.keyware.shandan.bianmu.service.DirectoryMetadataService;
import com.keyware.shandan.bianmu.service.MetadataService;
import com.keyware.shandan.common.controller.BaseController;
import com.keyware.shandan.common.entity.Result;
import com.keyware.shandan.common.enums.SecretLevel;
import com.keyware.shandan.common.util.StreamUtil;
import com.keyware.shandan.common.util.StringUtils;
import com.keyware.shandan.system.constants.FormTypeEnum;
import com.keyware.shandan.system.entity.SysFile;
import com.keyware.shandan.system.entity.SysFormConfig;
import com.keyware.shandan.system.service.SysFileService;
import com.keyware.shandan.system.service.SysFormConfigService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 数据资源管理前端控制器
 * </p>
 *
 * @author Administrator
 * @since 2021/5/25
 */
@RestController
@RequestMapping("/business/metadata")
public class MetadataController extends BaseController<MetadataService, MetadataBasicVo, String> {

    @Autowired
    private MetadataService metadataService;

    @Autowired
    private DirectoryMetadataService directoryMetadataService;

    @Autowired
    private SysFileService sysFileService;

    @Autowired
    private DataLabelsService labelsService;

    @Autowired
    private SysFormConfigService formConfigService;

    @GetMapping("/")
    public ModelAndView index(ModelAndView mov) {
        mov.setViewName("business/metadata/metadata");
        Map<String, String> map = new HashMap<>();
        Arrays.stream(SecretLevel.values()).forEach(secret -> map.put(secret.name(), secret.getDesc()));
        mov.addObject("SecretLevel", map);
        return mov;
    }

    @PostMapping("/simple/page")
    public Result<Object> page(HashMap<String, Object> param) {
        int current = (int) param.getOrDefault("current", "1");
        int size = (int) param.getOrDefault("size", "10");
        String metadataName = (String) param.getOrDefault("metadataName", "");
        String reviewStatus = (String) param.getOrDefault("reviewStatus", "");
        String useStatus = (String) param.getOrDefault("useStatus", "");

        MetadataBasicVo metadata = new MetadataBasicVo();
        if (StringUtils.hasText(metadataName)) {
            metadata.setMetadataName(metadataName);
        }
        if (StringUtils.hasText(reviewStatus)) {
            metadata.setReviewStatus(ReviewStatus.valueOf(reviewStatus));
        }

        QueryWrapper<MetadataBasicVo> query = new QueryWrapper<>(metadata);
        if (StringUtils.hasText(useStatus)) {
            Collection<String> ids = new ArrayList<>();
            if ("used".equalsIgnoreCase(useStatus)) {
                ids = directoryMetadataService.getUsedMetadataIds();
            } else if ("unused".equalsIgnoreCase(useStatus)) {
                ids = directoryMetadataService.getUnusedMetadataIds();
            }
            query.exists("select 1 from dual where instr('" + wrapperId(ids) + "', '[' || ID || ']') > 0");
        }
        Page<MetadataBasicVo> resultData = metadataService.page(new Page<>(current, size), query);
        HashSet<String> ids = directoryMetadataService.getUsedMetadataIds();
        StreamUtil.as(resultData.getRecords()).peek(item -> {
            item.setUsed(ids.contains(item.getId()));
        }).toList();
        return Result.of(resultData);
    }

    @GetMapping("/edit")
    public ModelAndView edit(ModelAndView mav) {
        mav.setViewName("business/metadata/metadataEdit");
        mav.addObject("LabelConfigSet", labelsService.formConfigList());
        mav.addObject("metadataFormConfig", formConfigService.listByFormType(FormTypeEnum.metadataEditForm));
        return mav;
    }

    @GetMapping("/example")
    public ModelAndView example() {
        return new ModelAndView("business/metadata/example");
    }

    /**
     * 数据资源选择框页面
     *
     * @return
     */
    @GetMapping("/layer/choose")
    public ModelAndView chooseLayer() {
        return new ModelAndView("business/metadata/chooseLayer");
    }

    /**
     * 保存数据资源基础信息和详情表数据
     *
     * @param metadataBasic
     * @return
     */
    @PostMapping("/save/full")
    public Result<Boolean> saveFull(MetadataBasicVo metadataBasic) {
        return Result.of(metadataService.saveMetadataBasicAndDetailsList(metadataBasic));
    }

    @PostMapping("/save/all")
    public Result<Boolean> saveFullTest(@RequestBody MetadataBasicVo metadataBasic) {
        return Result.of(metadataService.saveMetadataBasicAndDetailsList(metadataBasic));
    }

    @GetMapping("/get/page")
    public Result<Object> getByPage(@RequestParam(value = "page", defaultValue = "1") int page,
                                    @RequestParam(value = "size", defaultValue = "10") int size) {
        return Result.of(metadataService.page(new Page<>(page, size)));
    }


    /**
     * 保存数据资源及文件，并关联目录
     *
     * @param metadata    数据资源
     * @param directoryId 目录ID
     * @param fileIds     文件ID
     * @return
     */
    @PostMapping("/save/file")
    public Result<Boolean> saveMetadataAndFiles(MetadataBasicVo metadata, String directoryId, String fileIds) {
        if (StringUtils.isBlankAny(directoryId, fileIds)) {
            return Result.of(null, false, "参数错误");
        }
        // 保存数据资源
        if (metadataService.save(metadata)) {
            // 保存目录数据资源关系
            directoryMetadataService.save(new DirectoryMetadataVo(directoryId, metadata.getId()));
            //更新文件信息
            List<SysFile> files = sysFileService.listByIds(Arrays.asList(fileIds.split(",")));
            files.stream().peek(file -> file.setEntityId(metadata.getId())).collect(Collectors.toList());
            sysFileService.updateBatchById(files);
        }
        return Result.of(null);
    }

    @PostMapping("/delete")
    public Result<Object> deleteByIds(String ids) {
        if (StringUtils.hasText(ids)) {
            metadataService.removeByIds(Arrays.asList(ids.split(",")));
        }
        return Result.of(null);
    }

    private <E> String wrapperId(Collection<E> ids) {
        if (ids.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        ids.forEach(id -> sb.append("[").append(id).append("],"));
        return sb.toString();
    }
}
