package de.effigenix.loadtest.util;

import java.time.LocalDate;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Hilfsklasse zum Erzeugen von JSON-Request-Bodies mit eindeutigen Werten.
 * Atomare Counter verhindern Unique-Constraint-Verletzungen bei parallelen Writes.
 */
public final class JsonBodyBuilder {

    private static final AtomicInteger ARTICLE_SEQ = new AtomicInteger(10000);
    private static final AtomicInteger SUPPLIER_SEQ = new AtomicInteger(10000);
    private static final AtomicInteger CUSTOMER_SEQ = new AtomicInteger(10000);
    private static final AtomicInteger CATEGORY_SEQ = new AtomicInteger(10000);

    private JsonBodyBuilder() {}

    public static String loginBody(String username, String password) {
        return """
                {"username":"%s","password":"%s"}""".formatted(username, password);
    }

    public static String createArticleBody(String categoryId) {
        int seq = ARTICLE_SEQ.getAndIncrement();
        return """
                {"name":"Lasttest-Artikel-%d","articleNumber":"LT-%05d","categoryId":"%s","unit":"KG","priceModel":"WEIGHT_BASED","price":9.99}"""
                .formatted(seq, seq, categoryId);
    }

    public static String updateArticleBody() {
        return """
                {"name":"Aktualisiert-%d"}""".formatted(System.nanoTime() % 100000);
    }

    public static String createSupplierBody() {
        int seq = SUPPLIER_SEQ.getAndIncrement();
        return """
                {"name":"Lasttest-Lieferant-%d","phone":"0711-%07d"}"""
                .formatted(seq, seq);
    }

    public static String updateSupplierBody() {
        return """
                {"name":"Aktualisiert-Lieferant-%d"}""".formatted(System.nanoTime() % 100000);
    }

    public static String createCustomerBody() {
        int seq = CUSTOMER_SEQ.getAndIncrement();
        return """
                {"name":"Lasttest-Kunde-%d","type":"B2B","street":"Teststr. %d","postalCode":"70173","city":"Stuttgart","country":"DE","phone":"0711-%07d"}"""
                .formatted(seq, seq, seq);
    }

    public static String updateCustomerBody() {
        return """
                {"name":"Aktualisiert-Kunde-%d"}""".formatted(System.nanoTime() % 100000);
    }

    public static String createCategoryBody() {
        int seq = CATEGORY_SEQ.getAndIncrement();
        return """
                {"name":"Lasttest-Kategorie-%d","description":"Automatisch erzeugt"}"""
                .formatted(seq);
    }

    public static String createStorageLocationBody() {
        return """
                {"name":"LT-Lager-%d","storageType":"DRY_STORAGE"}"""
                .formatted(System.nanoTime() % 100000);
    }

    public static String createStockBody(String articleId, String storageLocationId) {
        return """
                {"articleId":"%s","storageLocationId":"%s","minimumLevelAmount":"10","minimumLevelUnit":"KG"}"""
                .formatted(articleId, storageLocationId);
    }

    public static String planBatchBody(String recipeId) {
        var today = LocalDate.now();
        var bestBefore = today.plusDays(14);
        return """
                {"recipeId":"%s","plannedQuantity":"10","plannedQuantityUnit":"KG","productionDate":"%s","bestBeforeDate":"%s"}"""
                .formatted(recipeId, today, bestBefore);
    }

    public static String completeBatchBody() {
        return """
                {"actualQuantity":"9.5","actualQuantityUnit":"KG","waste":"0.5","wasteUnit":"KG","remarks":"Lasttest"}""";
    }

    public static String cancelProductionOrderBody() {
        return """
                {"reason":"Lasttest-Stornierung"}""";
    }

    public static String createProductionOrderBody(String recipeId) {
        return """
                {"recipeId":"%s","plannedQuantity":"20","plannedQuantityUnit":"KG","plannedDate":"%s","priority":"NORMAL"}"""
                .formatted(recipeId, LocalDate.now().plusDays(1));
    }

    public static String rescheduleProductionOrderBody() {
        return """
                {"newPlannedDate":"%s"}""".formatted(LocalDate.now().plusDays(7));
    }
}
