package org.matrix.autotest.controller;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.matrix.autotest.utils.PageTools;
import org.matrix.database.entity.Action;
import org.matrix.database.entity.Move;
import org.matrix.database.service.IActionService;
import org.matrix.database.service.IMoveService;
import org.matrix.database.vo.CommonResult;
import org.matrix.database.vo.CommonResultObj;
import org.matrix.database.vo.MoveAction;
import org.matrix.exception.GlobalException;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.CachePut;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.http.ResponseEntity;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static java.util.Optional.ofNullable;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author mry
 * @since 2022-01-07
 */
@CrossOrigin
@RestController
@RequestMapping("/moves")
@Api(tags = "对行为move的基本操作")
public class MoveController {

    private final IActionService actionService;

    private final IMoveService moveService;

    public MoveController(IMoveService moveService, IActionService actionService) {
        this.moveService = moveService;
        this.actionService = actionService;
    }


    @GetMapping
    @Cacheable(cacheNames = "moveNames",
            key = "#p0", condition = "#p0 != null ",
            unless = "#result.statusCodeValue != 200")
    public ResponseEntity<CommonResultObj<String>> findNameById(@RequestParam Integer moveId) {
        String name = ofNullable(moveService.getById(moveId))
                .orElseThrow(() -> new GlobalException(String.format("没有找到id = %d 的move对象名称", moveId)))
                .getName();
        return CommonResult.success(name, "查询成功");
    }

    /**
     * 分页查询所有行为
     *
     * @param pageSize  每页多少条数据
     * @param pageNum   当前第几页
     * @param name      行为名称
     * @param projectId 项目id
     * @return 分页查询的结果, 行为
     */
    @ApiOperation(value = "分页查询行为")
    @GetMapping("/{projectId}")
    @Cacheable(cacheNames = "movePageName",
            key = "#pageNum + '_' + #pageSize + '_' + #projectId",
            condition = "#pageNum != null && #pageSize != null",
            unless = "#result.statusCodeValue != 200")
    public ResponseEntity<CommonResultObj<Page<Move>>> findPageConnects(
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(required = false, defaultValue = "") String name,
            @PathVariable Long projectId) {
        Page<Move> results = Optional.ofNullable(moveService.page(Page.of(pageNum, pageSize)
                , Wrappers.lambdaQuery(Move.class).eq(Move::getProjectId, projectId)
                        .like(StringUtils.hasLength(name)
                                , Move::getName, name))).orElse(new Page<>());
        PageTools.pageTool(pageSize, pageNum, results);
        return CommonResult.success(results, "查询成功");
    }

    /**
     * 条件查询行为
     *
     * @param pageSize  每页多少条数据
     * @param pageNum   当前第几页
     * @param name      行为名称
     * @param projectId 项目id
     * @return 分页查询的结果, 行为
     */
    @ApiOperation(value = "条件查询行为")
    @GetMapping("/condition/{projectId}")
    public ResponseEntity<CommonResultObj<Page<Move>>> findConditionConnects(
            @RequestParam(defaultValue = "10") int pageSize,
            @RequestParam(defaultValue = "1") int pageNum,
            @RequestParam(required = false, defaultValue = "") String name,
            @PathVariable Long projectId) {
        Page<Move> results = Optional.ofNullable(moveService.page(Page.of(pageNum, pageSize)
                , Wrappers.lambdaQuery(Move.class).eq(Move::getProjectId, projectId)
                        .like(StringUtils.hasLength(name)
                                , Move::getName, name))).orElse(new Page<>());
        PageTools.pageTool(pageSize, pageNum, results);
        return CommonResult.success(results, "查询成功");
    }

    /**
     * 输入行为主键id,查询出行为以及行为下包含的所有动作
     *
     * @param moveId 行为id
     * @return {@link MoveAction}
     */
    @ApiOperation(value = "根据行为id查,行为以及,行为下的动作")
    @GetMapping("/move/{moveId}")
    @Cacheable(cacheNames = "moveNames",
            key = "#moveId",
            condition = "#p0 != null",
            unless = "#result.statusCodeValue != 200")
    public ResponseEntity<CommonResultObj<MoveAction>> findByIdMoveAction(@PathVariable Long moveId) {
        Move byId = moveService.getById(moveId);
        if (byId == null) {
            throw new GlobalException("不存在行为");
        }
        Move move = ofNullable(moveService.getById(moveId))
                .orElseThrow(() -> new GlobalException(String.format("没有查到指定的行为,你提供的行为id是%d", moveId)));
        List<Action> actionList = ofNullable(actionService.list(Wrappers.lambdaQuery(Action.class)
                .eq(Action::getMoveId, moveId)))
                .orElse(new ArrayList<>());
        MoveAction ma = new MoveAction(move, actionList);
        return CommonResult.success(ma, "查询成功");
    }

    /**
     * 添加行为和动作(可以单独添加行为)
     *
     * @param moveAction 行为以及行为下的动作
     * @return 添加的行为和动作, 以及是否添加成功的提示信息
     */
    @ApiOperation(value = "添加行为和动作")
    @PostMapping
    @Caching(
            put = {@CachePut(cacheNames = "moveNames", key = "#result.body.data.move.id",
                    condition = "#p0 != null", unless = "#result.statusCodeValue != 200")
            },
            evict = {@CacheEvict(cacheNames = "movePageName", allEntries = true)})
    public ResponseEntity<CommonResultObj<MoveAction>> insertMoveAction(@RequestBody MoveAction moveAction) {
        Boolean moveBoolean = Optional.of(moveService.save(moveAction.getMove()))
                .orElseThrow(GlobalException::new);
        Long id = moveAction.getMove().getId();
        if (moveAction.getAction().size() != 0) {
            for (Action action : moveAction.getAction()) {
                action.setMoveId(id);
            }
        }
        boolean actionBoolean = actionService.saveBatch(moveAction.getAction());
        if (moveAction.getAction().size() == 0) {
            actionBoolean = true;
        }
        return moveBoolean && actionBoolean
                ? CommonResult.success(moveAction, "添加成功")
                : CommonResult.failed("添加失败");
    }

    /**
     * 修改行为,根据行为id修改动作
     *
     * @param moveAction 行为以及行为下的动作
     * @return {@link MoveAction}
     */
    @ApiOperation(value = "修改行为以及动作")
    @PutMapping
    @Transactional(rollbackFor = Exception.class)
    @Caching(
            put = {@CachePut(cacheNames = "moveNames", key = "#result.body.data.move.id",
                    condition = "#p0 != null", unless = "#result.statusCodeValue != 200")},
            evict = {
                    @CacheEvict(cacheNames = "movePageName", allEntries = true, condition = "#p0 != null "),
                    @CacheEvict(cacheNames = "moveNames", key = "#p0.move.id", condition = "#p0 != null ")})
    public ResponseEntity<CommonResultObj<MoveAction>> updateMoveAction(@RequestBody MoveAction moveAction) {
        Boolean update = Optional.of(moveService.updateById(moveAction.getMove()))
                .orElseThrow(GlobalException::new);
        Boolean delete = Optional.of(actionService.remove(Wrappers.lambdaQuery(Action.class)
                        .eq(Action::getMoveId, moveAction.getMove().getId())))
                .orElseThrow(() -> new GlobalException("删除失败"));
        Long id = moveAction.getMove().getId();
        moveAction.getAction().forEach(
                action -> action.setMoveId(id)
        );
        Boolean saveOrUpdate = Optional.of(actionService.saveOrUpdateBatch(moveAction.getAction()))
                .orElseThrow(() -> new GlobalException("失败"));
        return update
                ? CommonResult.success(moveAction, "修改成功")
                : CommonResult.failed(moveAction, "修改失败");
    }

    /**
     * 删除行为和动作
     *
     * @param moveId 行为id
     * @return 是否删除成功
     */
    @CacheEvict(cacheNames = "moveNames", key = "#p0")
    @ApiOperation(value = "删除行为和动作")
    @DeleteMapping("/{moveId}")
    @Transactional(rollbackFor = Exception.class)
    @Caching(evict = {
            @CacheEvict(cacheNames = "movePageName", allEntries = true, condition = "#p0 != null"),
            @CacheEvict(cacheNames = "moveNames", key = "#moveId", condition = "#p0!= null")})
    public ResponseEntity<CommonResultObj<MoveAction>> deleteMoveAction(@PathVariable Long moveId) {
        Boolean moveBoolean = Optional.of(moveService.removeById(moveId))
                .orElseThrow(() -> new GlobalException(String.format("没有查到指定的行为,你提供的行为id是%d", moveId)));
        Boolean actionBoolean = Optional.of(actionService.remove(Wrappers.lambdaQuery(Action.class)
                        .eq(moveId != 0, Action::getMoveId, moveId)))
                .orElseThrow(() -> new GlobalException(String.format("没有查到指定的行为,你提供的行为id是%d", moveId)));
        return moveBoolean
                ? CommonResult.success("删除成功")
                : CommonResult.failed("删除失败或不存在");
    }

}
