package de.frigosped.dc.resource;

import de.frigosped.dc.service.CheckOrchestrationService;
import jakarta.inject.Inject;
import jakarta.ws.rs.*;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.Response;
import org.eclipse.microprofile.openapi.annotations.Operation;
import org.eclipse.microprofile.openapi.annotations.tags.Tag;
import org.jboss.logging.Logger;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * REST-Endpunkte des Dokumenten-Check-Backend.
 *
 * POST /check/{projectId}
 *   → Reiht das Projekt in eine sequentielle Warteschlange ein (202 sofort).
 *   → Projekte werden strikt nacheinander verarbeitet (kein paralleler Betrieb).
 *
 * GET /check/health
 *   → Einfacher Health-Check inkl. Warteschlangenlänge.
 */
@Path("/check")
@Produces(MediaType.APPLICATION_JSON)
@Tag(name = "Dokumenten-Check", description = "KI-gestützte Dokumentenprüfung")
public class CheckResource {

    private static final Logger LOG = Logger.getLogger(CheckResource.class);

    // Single-Thread-Executor: garantiert sequentielle Abarbeitung.
    // Eingehende Aufrufe werden automatisch in die Warteschlange gelegt.
    private static final ExecutorService QUEUE =
        Executors.newSingleThreadExecutor(r -> {
            Thread t = new Thread(r, "dc-processing-thread");
            t.setDaemon(true);
            return t;
        });

    // Anzahl Projekte in der Warteschlange (inkl. laufendem)
    private static final AtomicInteger QUEUED = new AtomicInteger(0);

    @Inject
    CheckOrchestrationService orchestrationService;

    // =========================================================================
    // POST /check/{projectId}
    // =========================================================================

    @POST
    @Path("/{projectId}")
    @Operation(
        summary = "Reiht ein Projekt in die Verarbeitungswarteschlange ein",
        description = """
            Projekte werden strikt nacheinander verarbeitet.
            Der Aufruf kehrt sofort mit 202 zurück; die eigentliche Verarbeitung
            startet sobald alle vorher eingereihten Projekte abgeschlossen sind.

            Das Projekt muss im Status PENDING sein.
            Fortschritt: GET {ords}/api/dc/projects/{id}
            """
    )
    public Response startCheck(@PathParam("projectId") long projectId) {
        int position = QUEUED.incrementAndGet();

        QUEUE.submit(() -> {
            try {
                LOG.infof("Starte Projekt %d (Warteschlange: %d)", projectId, QUEUED.get());
                orchestrationService.process(projectId);
            } finally {
                QUEUED.decrementAndGet();
            }
        });

        return Response
            .accepted(Map.of(
                "message",        "Projekt in Warteschlange eingereiht",
                "project_id",     projectId,
                "queue_position", position,
                "hint",           "Fortschritt: GET /api/dc/projects/" + projectId
            ))
            .build();
    }

    // =========================================================================
    // GET /check/health
    // =========================================================================

    @GET
    @Path("/health")
    @Operation(summary = "Health-Check", description = "Gibt UP zurück inkl. Warteschlangenlänge.")
    public Response health() {
        return Response.ok(Map.of(
            "status",  "UP",
            "service", "dc-backend",
            "queued",  QUEUED.get()
        )).build();
    }
}
