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

import cn.hutool.core.util.StrUtil;
import com.github.xiaoymin.knife4j.annotations.ApiSupport;
import com.yiring.common.core.Result;
import com.yiring.common.domain.BasicEntity;
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.DictItem;
import com.yiring.dict.domain.DictItemRepository;
import com.yiring.dict.param.DictItemParam;
import com.yiring.dict.param.SelectorDictItemParam;
import com.yiring.dict.vo.DictItemVo;
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.Objects;
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.Page;
import org.springframework.data.jpa.domain.Specification;
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 = -95)
@Tag(name = "字典选项管理", description = "DictItem")
@RestController
@RequestMapping("/sys/dict/item/")
@RequiredArgsConstructor
public class DictItemController {

    final DictItemRepository dictItemRepository;

    @Operation(summary = "新增")
    @PostMapping("add")
    public Result<String> add(@ParameterObject @Validated({ Group.Add.class }) DictItemParam param) {
        DictItem entity = new DictItem();
        BeanUtils.copyProperties(param, entity);
        entity.setDict(Dict.builder().id(param.getDictId()).build());
        dictItemRepository.saveAndFlush(entity);
        return Result.ok();
    }

    @Operation(summary = "修改")
    @PostMapping("modify")
    public Result<String> modify(@ParameterObject @Validated({ Group.Edit.class }) DictItemParam param) {
        DictItem entity = RepositoryUtil.find(dictItemRepository, param.getId());
        BeanUtils.copyProperties(param, entity);
        dictItemRepository.saveAndFlush(entity);
        return Result.ok();
    }

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

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

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

    @Operation(summary = "选项查询")
    @GetMapping("selector")
    public Result<ArrayList<OptionVo>> selector(@ParameterObject @Validated SelectorDictItemParam param) {
        if (StrUtil.isBlank(param.getDictId()) && StrUtil.isBlank(param.getDictCode())) {
            throw BusinessException.i18n("Code.101001");
        }

        Specification<DictItem> specification = Specifications.exist((root, query, cb, predicates) -> {
            if (Objects.nonNull(param.getDisabled())) {
                predicates.add(cb.equal(root.get(DictItem.Fields.disabled), param.getDisabled()));
            }
            if (Objects.nonNull(param.getDictId())) {
                predicates.add(cb.equal(root.get(DictItem.Fields.dict).get(BasicEntity.Fields.id), param.getDictId()));
            }
            if (Objects.nonNull(param.getDictCode())) {
                predicates.add(cb.equal(root.get(DictItem.Fields.dict).get(Dict.Fields.code), param.getDictCode()));
            }
        });

        List<DictItem> items = dictItemRepository.findAll(specification);
        ArrayList<OptionVo> vos = items
            .stream()
            .map(item ->
                OptionVo
                    .builder()
                    .value(item.getId())
                    .label(item.getName())
                    .extra(item.getValue())
                    .disabled(item.getDisabled())
                    .build()
            )
            .collect(Collectors.toCollection(ArrayList::new));
        return Result.ok(vos);
    }
}
