package com.writeoff.module.audit.repository;

import com.writeoff.module.audit.model.AuditTask;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicLong;

@Repository
@ConditionalOnProperty(prefix = "app.repository", name = "mode", havingValue = "in-memory")
public class InMemoryAuditTaskRepository implements AuditTaskRepository {
    private final ConcurrentHashMap<Long, AuditTask> store = new ConcurrentHashMap<>();
    private final AtomicLong idGenerator = new AtomicLong(3000);

    @Override
    public AuditTask save(AuditTask task) {
        if (task.getId() == null) {
            AuditTask newTask = new AuditTask(
                    idGenerator.incrementAndGet(),
                    task.getMeetingId(),
                    task.getNode(),
                    task.getAssigneeUserId(),
                    task.getStatus(),
                    task.getOpinion()
            );
            store.put(newTask.getId(), newTask);
            return newTask;
        }
        store.put(task.getId(), task);
        return task;
    }

    @Override
    public Optional<AuditTask> findById(Long id) {
        return Optional.ofNullable(store.get(id));
    }

    @Override
    public List<AuditTask> findAll() {
        return new ArrayList<>(store.values());
    }

    @Override
    public Optional<AuditTask> findLatestByMeetingId(Long meetingId) {
        return store.values().stream()
                .filter(t -> t.getMeetingId().equals(meetingId))
                .max(Comparator.comparingLong(AuditTask::getId));
    }

    @Override
    public int withdrawPendingByMeetingId(Long meetingId, String reason, Long operatorUserId) {
        int count = 0;
        List<Long> toRemove = new ArrayList<Long>();
        for (Map.Entry<Long, AuditTask> e : store.entrySet()) {
            AuditTask task = e.getValue();
            if (task.getMeetingId().equals(meetingId) && "PENDING".equals(task.getStatus().name())) {
                toRemove.add(e.getKey());
            }
        }
        for (Long id : toRemove) {
            store.remove(id);
            count++;
        }
        return count;
    }

    @Override
    public void transfer(Long taskId, Long toUserId, String reason, Long operatorUserId) {
        AuditTask task = store.get(taskId);
        if (task == null) {
            throw new IllegalArgumentException("task not found");
        }
        task.setAssigneeUserId(toUserId);
        task.setOpinion(reason == null ? task.getOpinion() : ("转审:" + reason));
        task.setTimeoutLevel(0);
        store.put(taskId, task);
    }

    @Override
    public int batchRemind(List<Long> taskIds, Long operatorUserId) {
        int count = 0;
        for (Long taskId : taskIds) {
            if (store.containsKey(taskId)) {
                count++;
            }
        }
        return count;
    }

    @Override
    public Map<String, Object> slaStat() {
        Map<String, Object> data = new LinkedHashMap<>();
        data.put("pendingTotal", store.size());
        data.put("timeout4h", 0);
        data.put("timeout12h", 0);
        data.put("timeout24h", 0);
        return data;
    }
}
