/* (C) 2023 YiRing, Inc. */
package com.yiring.dict.web;

import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.yiring.common.core.Result;
import com.yiring.common.exception.BusinessException;
import com.yiring.common.param.IdParam;
import com.yiring.common.param.IdsParam;
import com.yiring.common.param.PageParam;
import com.yiring.common.util.Commons;
import com.yiring.common.utils.RepositoryUtil;
import com.yiring.common.utils.Specifications;
import com.yiring.common.validation.group.Group;
import com.yiring.common.vo.OptionVo;
import com.yiring.common.vo.PageVo;
import com.yiring.dict.domain.Dict;
import com.yiring.dict.domain.DictRepository;
import com.yiring.dict.param.DictParam;
import com.yiring.dict.vo.DictVo;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springdoc.core.annotations.ParameterObject;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * 数据字典管理
 *
 * @author Jim
 * @version 0.1
 * 2023/1/20 15:29
 */

@Slf4j
@Validated
@ApiSupport(order = -96)
@Tag(name = "字典管理", description = "Dict")
@RestController
@RequestMapping("/sys/dict/")
@RequiredArgsConstructor
public class DictController {

    final DictRepository dictRepository;

    @Operation(summary = "新增")
    @PostMapping("add")
    public Result<String> add(@ParameterObject @Validated({ Group.Add.class }) DictParam param) {
        if (has(param.getCode())) {
            throw BusinessException.i18n("Code.101000");
        }

        Dict entity = new Dict();
        BeanUtils.copyProperties(param, entity);
        dictRepository.saveAndFlush(entity);
        return Result.ok();
    }

    @Operation(summary = "修改")
    @PostMapping("modify")
    public Result<String> modify(@ParameterObject @Validated({ Group.Edit.class }) DictParam param) {
        Dict entity = RepositoryUtil.find(dictRepository, param.getId());
        if (!entity.getCode().equals(param.getCode())) {
            throw BusinessException.i18n("Code.101002");
        }

        BeanUtils.copyProperties(param, entity);
        dictRepository.saveAndFlush(entity);
        return Result.ok();
    }

    @Operation(summary = "删除")
    @PostMapping("remove")
    public Result<String> remove(@ParameterObject @Validated IdsParam param) {
        List<Dict> dictList = dictRepository.findAllById(param.toIds());
        dictRepository.deleteAll(dictList);
        return Result.ok();
    }

    @Operation(summary = "查询")
    @GetMapping("find")
    public Result<DictVo> find(@ParameterObject @Validated IdParam param) {
        Dict entity = RepositoryUtil.find(dictRepository, param.getId());
        DictVo vo = Commons.transform(entity, DictVo.class);
        return Result.ok(vo);
    }

    @Operation(summary = "分页查询")
    @GetMapping("page")
    public Result<PageVo<DictVo>> page(@ParameterObject @Validated PageParam param) {
        Page<Dict> page = dictRepository.findAll(Specifications.exist(), PageParam.toPageable(param));
        List<DictVo> data = Commons.transform(page.getContent(), DictVo.class);
        PageVo<DictVo> vo = PageVo.build(data, page.getTotalElements(), page.getTotalPages());
        return Result.ok(vo);
    }

    @Operation(summary = "选项查询")
    @GetMapping("selector")
    public Result<ArrayList<OptionVo>> selector() {
        List<Dict> dictList = dictRepository.findAll(Specifications.exist());
        ArrayList<OptionVo> vos = dictList
            .stream()
            .map(dict ->
                OptionVo
                    .builder()
                    .value(dict.getId())
                    .label(dict.getName())
                    .extra(dict.getCode())
                    .disabled(dict.getDisabled())
                    .build()
            )
            .collect(Collectors.toCollection(ArrayList::new));
        return Result.ok(vos);
    }

    /**
     * 检查是否存在已有相同编码的字典
     *
     * @param code 字典编码
     * @return 是否存在
     */
    private boolean has(String code) {
        Dict entity = Dict.builder().code(code).build();
        return dictRepository.count(Example.of(entity)) > 0;
    }
}
