package de.assecutor.votianlt.pages.service;

import de.assecutor.votianlt.model.Counter;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.data.mongodb.core.FindAndModifyOptions;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.stereotype.Service;

@Service
public class SequenceGeneratorService {

    public static final String CUSTOMER_NUMBER_SEQ = "customerNumber";
    public static final int CUSTOMER_NUMBER_START = 10000;

    private final MongoTemplate mongoTemplate;

    public SequenceGeneratorService(MongoTemplate mongoTemplate) {
        this.mongoTemplate = mongoTemplate;
    }

    public int nextCustomerNumber() {
        return (int) nextSequence(CUSTOMER_NUMBER_SEQ, CUSTOMER_NUMBER_START);
    }

    private long nextSequence(String sequenceId, long startValue) {
        ensureInitialized(sequenceId, startValue - 1);
        Counter updated = mongoTemplate.findAndModify(
                Query.query(Criteria.where("_id").is(sequenceId)),
                new Update().inc("sequence", 1),
                FindAndModifyOptions.options().returnNew(true),
                Counter.class);
        return updated != null ? updated.getSequence() : startValue;
    }

    private void ensureInitialized(String sequenceId, long initialValue) {
        boolean exists = mongoTemplate.exists(
                Query.query(Criteria.where("_id").is(sequenceId)),
                Counter.class);
        if (exists) {
            return;
        }
        Counter counter = new Counter();
        counter.setId(sequenceId);
        counter.setSequence(initialValue);
        try {
            mongoTemplate.insert(counter);
        } catch (DuplicateKeyException ignored) {
            // Ein anderer Thread hat den Counter gleichzeitig angelegt — passt.
        }
    }
}
