using Microsoft.AspNetCore.Mvc; // [Route], [ApiController], ControllerBase
using BibliotekaWspolna; // Customer
using Northwind.WebApi.Repozytoria; // IRepozytoriumCustomer

namespace Northwind.WebApi.Controllers;

// base address: api/klienci
[Route("api/[controller]")]
[ApiController]
public class KlienciController : ControllerBase
{
  private readonly IRepozytoriumCustomer repo;

  // konstruktor wstrzykuje zarejestrowane repozytorium
  public KlienciController(IRepozytoriumCustomer repo)
  {
    this.repo = repo;
  }

  // GET: api/klienci
  // GET: api/klienci/?kraj=[kraj]
  // Zawsze zwraca listę klientów, nawet jeżeli ta jest pusta
  [HttpGet]
  [ProducesResponseType(200, Type = typeof(IEnumerable<Customer>))]
  public async Task<IEnumerable<Customer>> OdczytajKlientow(string? kraj)
  {
    if (string.IsNullOrWhiteSpace(kraj))
    {
      return await repo.OdczytajWszystkoAsync();
    }
    else
    {
      return (await repo.OdczytajWszystkoAsync())
        .Where(klient => klient.Country == kraj);
    }
  }

  // GET: api/klienci/[id]
  [HttpGet("{id}", Name = nameof(OdczytajKlienta))] // nazwana ścieżka
  [ProducesResponseType(200, Type = typeof(Customer))]
  [ProducesResponseType(404)]
  public async Task<IActionResult> OdczytajKlienta(string id)
  {
    Customer? c = await repo.OdczytajAsync(id);
    if (c == null)
    {
      return NotFound(); // 404 Resource not found
    }
    return Ok(c); // 200 OK with customer in body
  }

  // POST: api/klienci
  // BODY: Customer (JSON, XML)
  [HttpPost]
  [ProducesResponseType(201, Type = typeof(Customer))]
  [ProducesResponseType(400)]
  public async Task<IActionResult> Utworz([FromBody] Customer k)
  {
    if (k == null)
    {
      return BadRequest(); // 400 Bad request
    }

    Customer? dodanyKlient = await repo.UtworzAsync(k);

    if (dodanyKlient == null)
    {
      return BadRequest("Repozytorium nie utworzyło klienta.");
    }
    else
    {
      return CreatedAtRoute( // 201 Created
        routeName: nameof(OdczytajKlienta),
        routeValues: new { id = dodanyKlient.CustomerId.ToLower() },
        value: dodanyKlient);
    }
  }

  // PUT: api/klienci/[id]
  // BODY: Customer (JSON, XML)
  [HttpPut("{id}")]
  [ProducesResponseType(204)]
  [ProducesResponseType(400)]
  [ProducesResponseType(404)]
  public async Task<IActionResult> Aktualizuj(
    string id, [FromBody] Customer k)
  {
    id = id.ToUpper();
    k.CustomerId = k.CustomerId.ToUpper();

    if (k == null || k.CustomerId != id)
    {
      return BadRequest(); // 400 Bad request
    }

    Customer? existing = await repo.OdczytajAsync(id);
    if (existing == null)
    {
      return NotFound(); // 404 Resource not found
    }

    await repo.AktualizujAsync(id, k);

    return new NoContentResult(); // 204 No content
  }

  // DELETE: api/klienci/[id]
  [HttpDelete("{id}")]
  [ProducesResponseType(204)]
  [ProducesResponseType(400)]
  [ProducesResponseType(404)]
  public async Task<IActionResult> Usun(string id)
  {
      // przygotuj szczegółowe dane problemu
      if (id == "bad")
    {
      ProblemDetails szczegolyProblemu = new()
      {
        Status = StatusCodes.Status400BadRequest,
        Type = "https://localhost:5001/klienci/nie-mozna-usunac",
        Title = $"Klient {id} został znaleziony, ale nie udało się go usunąć.",
        Detail = "Dodatkowe szczegóły, takie jak nazwa firmy, kraj itp. ",
        Instance = HttpContext.Request.Path
      };
      return BadRequest(szczegolyProblemu); // 400 Bad Request
    }

    Customer? existing = await repo.OdczytajAsync(id);
    if (existing == null)
    {
      return NotFound(); // 404 Resource not found
    }

    bool? usuniete = await repo.UsunAsync(id);

    if (usuniete.HasValue && usuniete.Value) // skrócony iloczyn logiczny
    {
      return new NoContentResult(); // 204 No content
    }
    else
    {
      return BadRequest( // 400 Bad request
        $"Klient {id} został znaleziony, ale nie udało się go usunąć.");
    }
  }
}
