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

import cn.axzo.workflow.common.model.dto.SimpleDocDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ApproverReadStatusDTO;
import cn.axzo.workflow.common.model.request.bpmn.process.doc.ChangeApproverReadStatusDTO;
import cn.axzo.workflow.core.repository.entity.ExtAxReadRecord;
import cn.axzo.workflow.core.repository.mapper.ExtAxReadRecordMapper;
import cn.axzo.workflow.core.service.ExtAxModelDocService;
import cn.axzo.workflow.core.service.ExtAxReadRecordService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.TaskService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

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

/**
 * 审批人关联文档阅读记录表服务实现
 *
 * @author wangli
 * @since 2025-04-02 10:06
 */
@Service
@Slf4j
public class ExtAxReadRecordServiceImpl extends ServiceImpl<ExtAxReadRecordMapper, ExtAxReadRecord> implements ExtAxReadRecordService {
    private static final Object lock = new Object();
    @Resource
    private ExtAxReadRecordMapper extAxReadRecordMapper;
    @Resource
    private TaskService taskService;
    @Resource
    private ExtAxModelDocService modelDocService;

    @Override
    public List<SimpleDocDTO> queryReadStatus(ApproverReadStatusDTO dto) {
        ExtAxReadRecord entity = new ExtAxReadRecord();
        entity.setProcessInstanceId(dto.getProcessInstanceId());
        entity.setPersonId(Long.valueOf(dto.getAssigner().getPersonId()));
        ExtAxReadRecord record = extAxReadRecordMapper.selectOne(buildWrapper(entity));
        return Objects.isNull(record) ? Collections.emptyList() : record.getReadStatus();
    }

    @Override
    public Boolean changeReadStatus(ChangeApproverReadStatusDTO dto) {
        ExtAxReadRecord entity = new ExtAxReadRecord();
        entity.setProcessInstanceId(dto.getProcessInstanceId());
        entity.setPersonId(Long.valueOf(dto.getAssigner().getPersonId()));

        ExtAxReadRecord record;
        synchronized (lock) {
            record = extAxReadRecordMapper.selectOne(buildWrapper(entity));
            if (Objects.isNull(record)) {
                // 新增全新阅读记录
                record = new ExtAxReadRecord();
                record.setProcessInstanceId(dto.getProcessInstanceId());
                record.setPersonId(Long.valueOf(dto.getAssigner().getPersonId()));
                record.setReadStatus(Lists.newArrayList(SimpleDocDTO.builder()
                        .id(dto.getDocId())
                        .tag(modelDocService.get(dto.getDocId()).getTag())
                        .readStatus(dto.getReadStatus())
                        .build()));
                extAxReadRecordMapper.insert(record);
                return true;
            } else {
                // 更新现有的阅读记录
                Optional<SimpleDocDTO> opt = record.getReadStatus().stream().filter(i -> Objects.equals(i.getId(), dto.getDocId())).findFirst();
                if (opt.isPresent()) {
                    opt.ifPresent(i -> i.setReadStatus(dto.getReadStatus()));
                } else {
                    record.getReadStatus().add(SimpleDocDTO.builder()
                            .id(dto.getDocId())
                            .tag(modelDocService.get(dto.getDocId()).getTag())
                            .readStatus(dto.getReadStatus())
                            .build());
                }
                extAxReadRecordMapper.updateById(record);
                return true;
            }
        }
    }

    private LambdaQueryWrapper<ExtAxReadRecord> buildWrapper(ExtAxReadRecord entity) {
        return new LambdaQueryWrapper<ExtAxReadRecord>()
                .eq(StringUtils.hasText(entity.getProcessInstanceId()), ExtAxReadRecord::getProcessInstanceId, entity.getProcessInstanceId())
                .eq(Objects.nonNull(entity.getPersonId()), ExtAxReadRecord::getPersonId, entity.getPersonId())
                ;
    }
}
