package com.cameleer.server.app.controller;

import com.cameleer.server.core.ingestion.ChunkAccumulator;
import com.cameleer.common.model.ExecutionChunk;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

/**
 * Ingestion endpoint for execution chunk data (ClickHouse pipeline).
 * <p>
 * Accepts single or array {@link ExecutionChunk} payloads and feeds them
 * into the {@link ChunkAccumulator}.
 */
@RestController
@RequestMapping("/api/v1/data")
@ConditionalOnBean(ChunkAccumulator.class)
@Tag(name = "Ingestion", description = "Data ingestion endpoints")
public class ChunkIngestionController {

    private static final Logger log = LoggerFactory.getLogger(ChunkIngestionController.class);

    private final ChunkAccumulator accumulator;
    private final ObjectMapper objectMapper;

    public ChunkIngestionController(ChunkAccumulator accumulator) {
        this.accumulator = accumulator;
        this.objectMapper = new ObjectMapper();
        this.objectMapper.registerModule(new JavaTimeModule());
        this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    }

    @PostMapping("/executions")
    @Operation(summary = "Ingest execution chunk")
    public ResponseEntity<Void> ingestChunks(@RequestBody String body) {
        try {
            String trimmed = body.strip();
            List<ExecutionChunk> chunks;
            if (trimmed.startsWith("[")) {
                chunks = objectMapper.readValue(trimmed, new TypeReference<List<ExecutionChunk>>() {});
            } else {
                ExecutionChunk single = objectMapper.readValue(trimmed, ExecutionChunk.class);
                chunks = List.of(single);
            }

            for (ExecutionChunk chunk : chunks) {
                accumulator.onChunk(chunk);
            }

            return ResponseEntity.accepted().build();
        } catch (Exception e) {
            log.warn("Failed to parse execution chunk payload: {}", e.getMessage());
            return ResponseEntity.badRequest().build();
        }
    }
}
