package com.cameleer.server.app.controller;

import com.cameleer.server.core.ingestion.IngestionService;
import com.cameleer.server.core.storage.model.MetricsSnapshot;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
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 agent metrics.
 * <p>
 * Accepts an array of {@link MetricsSnapshot}. Data is buffered
 * and flushed to PostgreSQL by the flush scheduler.
 */
@RestController
@RequestMapping("/api/v1/data")
@Tag(name = "Ingestion", description = "Data ingestion endpoints")
public class MetricsController {

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

    private final IngestionService ingestionService;
    private final ObjectMapper objectMapper;

    public MetricsController(IngestionService ingestionService, ObjectMapper objectMapper) {
        this.ingestionService = ingestionService;
        this.objectMapper = objectMapper;
    }

    @PostMapping("/metrics")
    @Operation(summary = "Ingest agent metrics",
            description = "Accepts an array of MetricsSnapshot objects")
    @ApiResponse(responseCode = "202", description = "Data accepted for processing")
    @ApiResponse(responseCode = "400", description = "Invalid payload")
    @ApiResponse(responseCode = "503", description = "Buffer full, retry later")
    public ResponseEntity<Void> ingestMetrics(@RequestBody String body) {
        List<MetricsSnapshot> metrics;
        try {
            metrics = parsePayload(body);
        } catch (JsonProcessingException e) {
            log.warn("Failed to parse metrics payload: {}", e.getMessage());
            return ResponseEntity.badRequest().build();
        }

        log.debug("Received {} metric(s) from agent(s)", metrics.size());

        boolean accepted = ingestionService.acceptMetrics(metrics);
        if (!accepted) {
            log.warn("Metrics buffer full ({} items), returning 503",
                    ingestionService.getMetricsBufferDepth());
            return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
                    .header("Retry-After", "5")
                    .build();
        }

        return ResponseEntity.accepted().build();
    }

    private List<MetricsSnapshot> parsePayload(String body) throws JsonProcessingException {
        String trimmed = body.strip();
        if (trimmed.startsWith("[")) {
            return objectMapper.readValue(trimmed, new TypeReference<>() {});
        } else {
            MetricsSnapshot single = objectMapper.readValue(trimmed, MetricsSnapshot.class);
            return List.of(single);
        }
    }
}
