package com.cameleer.server.app.controller;

import com.cameleer.server.app.AbstractPostgresIT;
import com.cameleer.server.app.TestSecurityHelper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;

import static java.util.concurrent.TimeUnit.SECONDS;
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;

/**
 * Integration tests for {@link DiagramRenderController}.
 * Seeds a diagram via the ingestion endpoint, then tests rendering.
 */
class DiagramRenderControllerIT extends AbstractPostgresIT {

    @Autowired
    private TestRestTemplate restTemplate;

    @Autowired
    private TestSecurityHelper securityHelper;

    private String jwt;
    private String viewerJwt;
    private String contentHash;

    /**
     * Seed a diagram and compute its content hash for render tests.
     */
    @BeforeEach
    void seedDiagram() {
        jwt = securityHelper.registerTestAgent("test-agent-diagram-render-it");
        viewerJwt = securityHelper.viewerToken();

        String json = """
                {
                  "routeId": "render-test-route",
                  "description": "Render test",
                  "version": 1,
                  "nodes": [
                    {"id": "n1", "type": "ENDPOINT", "label": "timer:tick"},
                    {"id": "n2", "type": "BEAN", "label": "myBean"},
                    {"id": "n3", "type": "TO", "label": "log:out"}
                  ],
                  "edges": [
                    {"source": "n1", "target": "n2", "edgeType": "FLOW"},
                    {"source": "n2", "target": "n3", "edgeType": "FLOW"}
                  ]
                }
                """;

        restTemplate.postForEntity(
                "/api/v1/data/diagrams",
                new HttpEntity<>(json, securityHelper.authHeaders(jwt)),
                String.class);

        // Wait for flush to storage and retrieve the content hash
        await().atMost(10, SECONDS).untilAsserted(() -> {
            String hash = jdbcTemplate.queryForObject(
                    "SELECT content_hash FROM route_diagrams WHERE route_id = 'render-test-route' LIMIT 1",
                    String.class);
            assertThat(hash).isNotNull();
            contentHash = hash;
        });
    }

    @Test
    void getSvg_withAcceptHeader_returnsSvg() {
        HttpHeaders headers = securityHelper.authHeadersNoBody(viewerJwt);
        headers.set("Accept", "image/svg+xml");

        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/diagrams/{hash}/render",
                HttpMethod.GET,
                new HttpEntity<>(headers),
                String.class,
                contentHash);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getHeaders().getContentType().toString()).contains("svg");
        assertThat(response.getBody()).contains("<svg");
    }

    @Test
    void getJson_withAcceptHeader_returnsJson() {
        HttpHeaders headers = securityHelper.authHeadersNoBody(viewerJwt);
        headers.set("Accept", "application/json");

        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/diagrams/{hash}/render",
                HttpMethod.GET,
                new HttpEntity<>(headers),
                String.class,
                contentHash);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).contains("nodes");
        assertThat(response.getBody()).contains("edges");
    }

    @Test
    void getNonExistentHash_returns404() {
        HttpHeaders headers = securityHelper.authHeadersNoBody(viewerJwt);
        headers.set("Accept", "image/svg+xml");

        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/diagrams/{hash}/render",
                HttpMethod.GET,
                new HttpEntity<>(headers),
                String.class,
                "nonexistent-hash-12345");

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
    }

    @Test
    void getWithNoAcceptHeader_defaultsToSvg() {
        HttpHeaders headers = securityHelper.authHeadersNoBody(viewerJwt);

        ResponseEntity<String> response = restTemplate.exchange(
                "/api/v1/diagrams/{hash}/render",
                HttpMethod.GET,
                new HttpEntity<>(headers),
                String.class,
                contentHash);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).contains("<svg");
    }
}
