package cn.stylefeng.workflow.instance.modular.manage.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.roses.kernel.db.api.factory.PageFactory;
import cn.stylefeng.roses.kernel.db.api.factory.PageResultFactory;
import cn.stylefeng.roses.kernel.db.api.pojo.page.PageResult;
import cn.stylefeng.roses.kernel.rule.exception.base.ServiceException;
import cn.stylefeng.roses.kernel.timer.api.enums.TimerJobStatusEnum;
import cn.stylefeng.workflow.api.entity.instance.RuntimeTimer;
import cn.stylefeng.workflow.instance.modular.manage.enums.RuntimeTimerExceptionEnum;
import cn.stylefeng.workflow.instance.modular.manage.mapper.RuntimeTimerMapper;
import cn.stylefeng.workflow.instance.modular.manage.pojo.request.RuntimeTimerRequest;
import cn.stylefeng.workflow.instance.modular.manage.service.RuntimeTimerService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
public class RuntimeTimerServiceImpl extends ServiceImpl<RuntimeTimerMapper, RuntimeTimer> implements RuntimeTimerService {

    @Override
    public void add(RuntimeTimerRequest runtimeTimerRequest) {
        RuntimeTimer runtimeTimer = new RuntimeTimer();
        BeanUtil.copyProperties(runtimeTimerRequest, runtimeTimer);

        runtimeTimer.setTimerStatus(TimerJobStatusEnum.RUNNING.getCode());

        this.save(runtimeTimer);
    }

    @Override
    public void removeAllInstanceTimer(Long instanceId) {
        if (instanceId == null) {
            return;
        }

        LambdaQueryWrapper<RuntimeTimer> runtimeTimerLambdaQueryWrapper = new LambdaQueryWrapper<>();
        runtimeTimerLambdaQueryWrapper.eq(RuntimeTimer::getInstanceId, instanceId);
        this.remove(runtimeTimerLambdaQueryWrapper);
    }

    @Override
    public void edit(RuntimeTimerRequest runtimeTimerRequest) {
        RuntimeTimer runtimeTimer = this.queryRuntimeTimer(runtimeTimerRequest);
        BeanUtil.copyProperties(runtimeTimerRequest, runtimeTimer);
        this.updateById(runtimeTimer);
    }

    @Override
    public RuntimeTimer detail(RuntimeTimerRequest runtimeTimerRequest) {
        return this.queryRuntimeTimer(runtimeTimerRequest);
    }

    @Override
    public PageResult<RuntimeTimer> findPage(RuntimeTimerRequest runtimeTimerRequest) {
        LambdaQueryWrapper<RuntimeTimer> wrapper = createWrapper(runtimeTimerRequest);
        Page<RuntimeTimer> sysRolePage = this.page(PageFactory.defaultPage(), wrapper);
        return PageResultFactory.createPageResult(sysRolePage);
    }

    @Override
    public List<RuntimeTimer> findList(RuntimeTimerRequest runtimeTimerRequest) {
        LambdaQueryWrapper<RuntimeTimer> wrapper = this.createWrapper(runtimeTimerRequest);

        wrapper.select(RuntimeTimer::getTimerName, RuntimeTimer::getTimerActionClass, RuntimeTimer::getTimerCron,
                RuntimeTimer::getParamRuntimeNodeJson, RuntimeTimer::getParamInstanceContextJson);

        return this.list(wrapper);
    }

    private RuntimeTimer queryRuntimeTimer(RuntimeTimerRequest runtimeTimerRequest) {
        RuntimeTimer runtimeTimer = this.getById(runtimeTimerRequest.getRuntimeNodeTimerId());
        if (ObjectUtil.isEmpty(runtimeTimer)) {
            throw new ServiceException(RuntimeTimerExceptionEnum.RUNTIME_TIMER_NOT_EXISTED);
        }
        return runtimeTimer;
    }

    private LambdaQueryWrapper<RuntimeTimer> createWrapper(RuntimeTimerRequest runtimeTimerRequest) {
        LambdaQueryWrapper<RuntimeTimer> queryWrapper = new LambdaQueryWrapper<>();

        Integer timerStatus = runtimeTimerRequest.getTimerStatus();
        queryWrapper.eq(ObjectUtil.isNotNull(timerStatus), RuntimeTimer::getTimerStatus, timerStatus);

        return queryWrapper;
    }

}