using System.Net.Http.Json;
using BigRegister.Api.Contracts;
using Microsoft.AspNetCore.Mvc.Testing;

namespace BigRegister.Tests;

public class IdempotencyTests(TestWebApplicationFactory factory) : IClassFixture<TestWebApplicationFactory>
{
  private readonly HttpClient _client = factory.CreateClient();

  private static HttpRequestMessage ChangeRequestWithKey(string key)
  {
    var req = new HttpRequestMessage(HttpMethod.Post, "/api/v1/change-requests")
    {
      Content = JsonContent.Create(new { straat = "Lange Voorhout 9", postcode = "2514 EA", woonplaats = "Den Haag" }),
    };
    req.Headers.Add("Idempotency-Key", key);
    return req;
  }

  [Fact]
  public async Task Replaying_the_same_idempotency_key_returns_the_same_reference_not_a_new_one()
  {
    var key = Guid.NewGuid().ToString();

    var first = await _client.SendAsync(ChangeRequestWithKey(key));
    first.EnsureSuccessStatusCode();
    var firstBody = await first.Content.ReadFromJsonAsync<ReferentieResponse>();

    var replay = await _client.SendAsync(ChangeRequestWithKey(key));
    replay.EnsureSuccessStatusCode();
    var replayBody = await replay.Content.ReadFromJsonAsync<ReferentieResponse>();

    Assert.Equal(firstBody!.Referentie, replayBody!.Referentie);
  }

  [Fact]
  public async Task Different_idempotency_keys_are_independent_submissions()
  {
    var first = await _client.SendAsync(ChangeRequestWithKey(Guid.NewGuid().ToString()));
    var second = await _client.SendAsync(ChangeRequestWithKey(Guid.NewGuid().ToString()));
    var firstBody = await first.Content.ReadFromJsonAsync<ReferentieResponse>();
    var secondBody = await second.Content.ReadFromJsonAsync<ReferentieResponse>();

    Assert.NotEqual(firstBody!.Referentie, secondBody!.Referentie);
  }

  [Fact]
  public async Task A_rejected_submission_replays_the_same_rejection_not_a_retry()
  {
    var key = Guid.NewGuid().ToString();
    var badRequest = new HttpRequestMessage(HttpMethod.Post, "/api/v1/change-requests")
    {
      Content = JsonContent.Create(new { straat = "Straat 1", postcode = "nope", woonplaats = "Den Haag" }),
    };
    badRequest.Headers.Add("Idempotency-Key", key);

    var first = await _client.SendAsync(badRequest);
    Assert.Equal(System.Net.HttpStatusCode.UnprocessableEntity, first.StatusCode);

    var replayRequest = new HttpRequestMessage(HttpMethod.Post, "/api/v1/change-requests")
    {
      Content = JsonContent.Create(new { straat = "Straat 1", postcode = "nope", woonplaats = "Den Haag" }),
    };
    replayRequest.Headers.Add("Idempotency-Key", key);
    var replay = await _client.SendAsync(replayRequest);
    Assert.Equal(System.Net.HttpStatusCode.UnprocessableEntity, replay.StatusCode);
  }
}
