package io.specto.hoverfly.ruletest;

import io.specto.hoverfly.junit.rule.HoverflyRule;
import org.json.JSONObject;
import org.junit.ClassRule;
import org.junit.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.RequestEntity;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.net.URI;

import static io.specto.hoverfly.junit.core.SimulationSource.dsl;
import static io.specto.hoverfly.junit.dsl.HoverflyDsl.service;
import static io.specto.hoverfly.junit.dsl.HttpBodyConverter.jsonWithSingleQuotes;
import static io.specto.hoverfly.junit.dsl.ResponseCreators.success;
import static io.specto.hoverfly.junit.dsl.matchers.HoverflyMatchers.any;
import static org.assertj.core.api.Assertions.assertThat;

public class HoverflyDslResponseTemplatingTest {


    @ClassRule
    public static HoverflyRule hoverflyRule = HoverflyRule.inSimulationMode(dsl(
            service("www.my-test.com")

                    // Path param for template
                    .get("/api/bookings/1")
                    .willReturn(success().body(jsonWithSingleQuotes(
                            "{'id':{{ Request.Path.[2] }},'origin':'London','destination':'Singapore','time':'2011-09-01T12:30','_links':{'self':{'href':'http://localhost/api/bookings/{{ Request.Path.[2] }}'}}}"
                    )))
                    // Query Param for template
                    .get("/api/bookings")
                    .queryParam("destination", "London")
                    .queryParam("page", any())
                    .willReturn(success().body(jsonWithSingleQuotes(
                            "{'id':'1', 'destination':'{{ Request.QueryParam.destination }}','time':'2011-09-01T12:30','_links':{'self':{'href':'http://localhost/api/bookings?page={{ Request.QueryParam.page }}'}}}"
                    )))

    )).printSimulationData();

    private final RestTemplate restTemplate = new RestTemplate();


    @Test
    public void shouldBeAbleToGenerateResponseFromRequestPathParam() throws Exception {
        // Given
        final RequestEntity<Void> getFlightRequest = RequestEntity.get(new URI("http://www.my-test.com/api/bookings/1")).build();

        // When
        final ResponseEntity<String> response = restTemplate.exchange(getFlightRequest, String.class);

        // Then
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        JSONObject body = new JSONObject(response.getBody());
        assertThat(body.getInt("id")).isEqualTo(1);
        assertThat(body.getJSONObject("_links")
                .getJSONObject("self")
                .getString("href")).isEqualTo("http://localhost/api/bookings/1");
    }

    @Test
    public void shouldBeAbleToGenerateResponseFromRequestQueryParam() throws Exception {
        // Given
        URI uri = UriComponentsBuilder.fromHttpUrl("http://www.my-test.com")
                .path("/api/bookings")
                .queryParam("destination", "London")
                .queryParam("page", 2)
                .build()
                .toUri();

        // When
        final ResponseEntity<String> response = restTemplate.getForEntity(uri, String.class);

        // Then
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        JSONObject body = new JSONObject(response.getBody());
        assertThat(body.getString("destination")).isEqualTo("London");
        assertThat(body.getJSONObject("_links")
                .getJSONObject("self")
                .getString("href")).isEqualTo("http://localhost/api/bookings?page=2");

    }
}

@@ -67,25 +67,137 @@
 nit.
-rule.HoverflyRule
+core.model.RequestFieldMatcher;%0Aimport io.specto.hoverfly.junit.rule.HoverflyRule;%0Aimport io.specto.hoverfly.models.SimpleBooking
 ;%0Aim
@@ -317,16 +317,59 @@
 Status;%0A
+import org.springframework.http.MediaType;%0A
 import o
@@ -586,16 +586,44 @@
 net.URI;
+%0Aimport java.time.LocalDate;
 %0A%0Aimport
@@ -725,31 +725,184 @@
 nit.
-dsl.HoverflyDsl.service
+core.model.RequestFieldMatcher.newJsonMatcher;%0Aimport static io.specto.hoverfly.junit.dsl.HoverflyDsl.service;%0Aimport static io.specto.hoverfly.junit.dsl.HttpBodyConverter.json
 ;%0Aim
@@ -2268,16 +2268,362 @@
      )))
+%0A                    // Request body for template%0A                    .put(%22/api/bookings/1%22)%0A                    .body(newJsonMatcher(json(new SimpleBooking(1, %22London%22, %22Hong Kong%22, null)).body()))%0A                    .willReturn(success().body(jsonWithSingleQuotes(%22%7B'id':'1', 'destination':'%7B%7B Request.Body 'jsonpath' '$.destination' %7D%7D'%7D%22)))
 %0A%0A    ))
@@ -4345,11 +4345,809 @@
 ;%0A%0A    %7D
+%0A%0A    @Test%0A    public void shouldBeAbleToGenerateResponseFromRequestBody() %7B%0A        // Given%0A        URI uri = UriComponentsBuilder.fromHttpUrl(%22http://www.my-test.com%22)%0A                .path(%22/api/bookings/1%22)%0A                .build()%0A                .toUri();%0A        RequestEntity%3CSimpleBooking%3E request = RequestEntity.put(uri)%0A                .contentType(MediaType.APPLICATION_JSON)%0A                .body(new SimpleBooking(1, %22London%22, %22Hong Kong%22, null));%0A%0A        // When%0A        final ResponseEntity%3CSimpleBooking%3E response = restTemplate.exchange(request, SimpleBooking.class);%0A%0A        // Then%0A        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);%0A        SimpleBooking body = response.getBody();%0A        assertThat(body.getDestination()).isEqualTo(%22Hong Kong%22);%0A    %7D
 %0A%7D%0A

Add test for templating using request body