package com.cameleer.server.app.controller;

import com.cameleer.server.core.detail.DetailService;
import com.cameleer.server.core.detail.ExecutionDetail;
import com.cameleer.server.core.storage.ExecutionStore;
import com.cameleer.server.core.storage.ExecutionStore.ProcessorRecord;
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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Endpoints for retrieving execution details and processor snapshots.
 * <p>
 * The detail endpoint returns a nested processor tree reconstructed from
 * individual processor records stored in PostgreSQL. The snapshot endpoint
 * returns per-processor exchange data (bodies and headers).
 */
@RestController
@RequestMapping("/api/v1/executions")
@Tag(name = "Detail", description = "Execution detail and processor snapshot endpoints")
public class DetailController {

    private final DetailService detailService;
    private final ExecutionStore executionStore;

    public DetailController(DetailService detailService,
                            ExecutionStore executionStore) {
        this.detailService = detailService;
        this.executionStore = executionStore;
    }

    @GetMapping("/{executionId}")
    @Operation(summary = "Get execution detail with nested processor tree")
    @ApiResponse(responseCode = "200", description = "Execution detail found")
    @ApiResponse(responseCode = "404", description = "Execution not found")
    public ResponseEntity<ExecutionDetail> getDetail(@PathVariable String executionId) {
        return detailService.getDetail(executionId)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    @GetMapping("/{executionId}/processors/{index}/snapshot")
    @Operation(summary = "Get exchange snapshot for a specific processor by index")
    @ApiResponse(responseCode = "200", description = "Snapshot data")
    @ApiResponse(responseCode = "404", description = "Snapshot not found")
    public ResponseEntity<Map<String, String>> getProcessorSnapshot(
            @PathVariable String executionId,
            @PathVariable int index) {
        List<ProcessorRecord> processors = executionStore.findProcessors(executionId);
        if (index < 0 || index >= processors.size()) {
            return ResponseEntity.notFound().build();
        }

        ProcessorRecord p = processors.get(index);
        Map<String, String> snapshot = new LinkedHashMap<>();
        if (p.inputBody() != null) snapshot.put("inputBody", p.inputBody());
        if (p.outputBody() != null) snapshot.put("outputBody", p.outputBody());
        if (p.inputHeaders() != null) snapshot.put("inputHeaders", p.inputHeaders());
        if (p.outputHeaders() != null) snapshot.put("outputHeaders", p.outputHeaders());

        return ResponseEntity.ok(snapshot);
    }

    @GetMapping("/{executionId}/processors/by-id/{processorId}/snapshot")
    @Operation(summary = "Get exchange snapshot for a specific processor by processorId")
    @ApiResponse(responseCode = "200", description = "Snapshot data")
    @ApiResponse(responseCode = "404", description = "Snapshot not found")
    public ResponseEntity<Map<String, String>> processorSnapshotById(
            @PathVariable String executionId,
            @PathVariable String processorId) {
        return detailService.getProcessorSnapshot(executionId, processorId)
            .map(ResponseEntity::ok)
            .orElse(ResponseEntity.notFound().build());
    }

    @GetMapping("/{executionId}/processors/by-seq/{seq}/snapshot")
    @Operation(summary = "Get exchange snapshot for a processor by seq number")
    @ApiResponse(responseCode = "200", description = "Snapshot data")
    @ApiResponse(responseCode = "404", description = "Snapshot not found")
    public ResponseEntity<Map<String, String>> processorSnapshotBySeq(
            @PathVariable String executionId,
            @PathVariable int seq) {
        return detailService.getProcessorSnapshotBySeq(executionId, seq)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }
}
