package com.cameleer.server.app.controller;

import com.cameleer.common.graph.RouteGraph;
import com.cameleer.server.core.agent.AgentInfo;
import com.cameleer.server.core.agent.AgentRegistryService;
import com.cameleer.server.core.ingestion.IngestionService;
import com.cameleer.server.core.ingestion.TaggedDiagram;
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.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
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 route diagrams.
 * <p>
 * Accepts both single {@link RouteGraph} and arrays. Data is written
 * synchronously to PostgreSQL via {@link IngestionService}.
 */
@RestController
@RequestMapping("/api/v1/data")
@Tag(name = "Ingestion", description = "Data ingestion endpoints")
public class DiagramController {

    private final IngestionService ingestionService;
    private final AgentRegistryService registryService;
    private final ObjectMapper objectMapper;

    public DiagramController(IngestionService ingestionService,
                             AgentRegistryService registryService,
                             ObjectMapper objectMapper) {
        this.ingestionService = ingestionService;
        this.registryService = registryService;
        this.objectMapper = objectMapper;
    }

    @PostMapping("/diagrams")
    @Operation(summary = "Ingest route diagram data",
            description = "Accepts a single RouteGraph or an array of RouteGraphs")
    @ApiResponse(responseCode = "202", description = "Data accepted for processing")
    public ResponseEntity<Void> ingestDiagrams(@RequestBody String body) throws JsonProcessingException {
        String instanceId = extractAgentId();
        AgentInfo agent = registryService.findById(instanceId);
        String applicationId = agent != null ? agent.applicationId() : "";
        String environment = agent != null ? agent.environmentId() : "";
        List<RouteGraph> graphs = parsePayload(body);

        for (RouteGraph graph : graphs) {
            ingestionService.ingestDiagram(new TaggedDiagram(instanceId, applicationId, environment, graph));
        }

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

    private String extractAgentId() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        return auth != null ? auth.getName() : "";
    }

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