package cn.axzo.workflow.core.service.impl;

import cn.axzo.workflow.common.model.dto.OrgStructureSnapshotInfo;
import cn.axzo.workflow.common.model.dto.SimpleTaskDTO;
import cn.axzo.workflow.common.model.request.bpmn.task.BpmnTaskDelegateAssigner;
import cn.axzo.workflow.core.repository.entity.ExtAxProcessLog;
import cn.axzo.workflow.core.repository.mapper.ExtAxProcessLogMapper;
import cn.axzo.workflow.core.service.ExtAxProcessLogService;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;

import static cn.axzo.workflow.common.constant.BpmnConstants.DUMMY_ASSIGNEE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.HIDDEN_ASSIGNEE_ID;
import static cn.axzo.workflow.common.constant.BpmnConstants.NO_ASSIGNEE;
import static cn.axzo.workflow.common.constant.BpmnConstants.ROBOT_ASSIGNEE_ID;
import static cn.axzo.workflow.core.common.enums.BpmnProcessTaskResultEnum.HANDLING;

/**
 * Api Log 表操服务实现
 *
 * @author wangli
 * @since 2024/4/3 10:41
 */
@Service
@Slf4j
public class ExtAxProcessLogServiceImpl implements ExtAxProcessLogService {
    @Resource
    private ExtAxProcessLogMapper extAxProcessLogMapper;

    @Override
    public Long insert(ExtAxProcessLog log) {
        extAxProcessLogMapper.insert(log);
        return log.getId();
    }

    @Override
    public void delete(ExtAxProcessLog deleteLog) {
        extAxProcessLogMapper.delete(buildQueryWrapper(deleteLog));
    }

    public void updateById(ExtAxProcessLog updateLog) {
        extAxProcessLogMapper.updateById(updateLog);
    }

    public void update(ExtAxProcessLog query, ExtAxProcessLog update) {
        extAxProcessLogMapper.update(update, buildQueryWrapper(query));
    }

    @Override
    public void updateAssigneeAndSnapshot(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee, OrgStructureSnapshotInfo snapshotInfo) {
        updateAssigneeAndSnapshot(queryLog, assignee, snapshotInfo, assignee.getAssignerName() + HANDLING.getDesc());

    }

    @Override
    public void updateAssigneeAndSnapshot(ExtAxProcessLog queryLog, BpmnTaskDelegateAssigner assignee, OrgStructureSnapshotInfo snapshotInfo, String operationDesc) {
        List<String> filterAssignee = Lists.newArrayList(NO_ASSIGNEE, HIDDEN_ASSIGNEE_ID, ROBOT_ASSIGNEE_ID,
                DUMMY_ASSIGNEE_ID, "system");
        if (Objects.isNull(assignee) || filterAssignee.contains(assignee.buildAssigneeId())) {
            return;
        }
        ExtAxProcessLog update = new ExtAxProcessLog();
        update.setOperationDesc(StringUtils.hasText(operationDesc) ? operationDesc : assignee.getAssignerName() + HANDLING.getDesc());
        update.setAssigneeFull(Lists.newArrayList(assignee));
        update.setAssigneeId(Long.valueOf(assignee.getPersonId()));
        update.setAssigneeTenantId(assignee.getTenantId());
        update.setAssigneeOuId(assignee.getOuId());
        update.setAssigneeName(assignee.getAssignerName());
        update.setExtra(snapshotInfo);
        extAxProcessLogMapper.update(update, buildQueryWrapper(queryLog));
    }

    @Override
    public List<ExtAxProcessLog> genericQuery(ExtAxProcessLog query) {
        return extAxProcessLogMapper.selectList(buildQueryWrapper(query));
    }

    @Override
    public ExtAxProcessLog findByProcessIdAndTaskIdWithDeleted(String processId, String taskId) {
        return extAxProcessLogMapper.findByProcessIdAndTaskIdWithDeleted(processId, taskId);
    }

    @Override
    public void restore(String processInstanceId, String taskId) {
        batchRestore(Lists.newArrayList(new SimpleTaskDTO(processInstanceId, taskId)));
    }

    @Override
    public void batchRestore(List<SimpleTaskDTO> tasks) {
        if (CollectionUtils.isEmpty(tasks)) {
            return;
        }
        tasks.forEach(task -> {
            if (StringUtils.hasText(task.getProcessInstanceId()) && StringUtils.hasText(task.getTaskId())) {
                extAxProcessLogMapper.restore(task.getProcessInstanceId(), task.getTaskId());
            }
        });
    }

    LambdaQueryWrapper<ExtAxProcessLog> buildQueryWrapper(ExtAxProcessLog log) {
        return new LambdaQueryWrapper<ExtAxProcessLog>()
                .eq(Objects.nonNull(log.getId()), ExtAxProcessLog::getId, log.getId())
                .eq(StringUtils.hasText(log.getProcessInstanceId()), ExtAxProcessLog::getProcessInstanceId, log.getProcessInstanceId())
                .eq(StringUtils.hasText(log.getActivityId()), ExtAxProcessLog::getActivityId, log.getActivityId())
                .eq(StringUtils.hasText(log.getActivityName()), ExtAxProcessLog::getActivityName, log.getActivityName())
                .eq(StringUtils.hasText(log.getTaskId()), ExtAxProcessLog::getTaskId, log.getTaskId())
                .eq(StringUtils.hasText(log.getTenantId()), ExtAxProcessLog::getTenantId, log.getTenantId())
                .eq(StringUtils.hasText(log.getStatus()), ExtAxProcessLog::getStatus, log.getStatus())
                .eq(Objects.nonNull(log.getAssigneeId()), ExtAxProcessLog::getAssigneeId, log.getAssigneeId())
                .eq(StringUtils.hasText(log.getAssigneeTenantId()), ExtAxProcessLog::getAssigneeTenantId, log.getAssigneeTenantId())
                .eq(StringUtils.hasText(log.getAssigneeOuId()), ExtAxProcessLog::getAssigneeOuId, log.getAssigneeOuId())
                .eq(ExtAxProcessLog::getIsDelete, log.getIsDelete());
    }
}
