package com.training.controller;

import com.training.entities.Person;
import com.training.exceptions.ManagePeoplesException;
import com.training.service.IPersonService;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/api/persons")
@RequiredArgsConstructor
public class PersonController {

    private final IPersonService personService;

    /**
     * Créer une nouvelle personne
     */
    @PostMapping
    public ResponseEntity<PersonApi> createPerson(@Valid @RequestBody PersonApi personApi) {
        log.info("POST /api/persons - Création d'une personne: {} {}",
                personApi.getFirstName(), personApi.getLastName());

        Person person = PersonMapper.toEntity(personApi);
        Person createdPerson = personService.createPerson(person);
        PersonApi response = PersonMapper.toApi(createdPerson);

        return ResponseEntity.status(HttpStatus.CREATED).body(response);
    }

    /**
     * Récupérer une personne par son ID
     */
    @GetMapping("/{id}")
    public ResponseEntity<PersonApi> getPersonById(@PathVariable Integer id) {
        log.info("GET /api/persons/{} - Récupération d'une personne", id);

        return personService.getPersonById(id)
                .map(PersonMapper::toApi)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    /**
     * Récupérer toutes les personnes
     */
    @GetMapping
    public ResponseEntity<List<PersonApi>> getAllPersons() {
        log.info("GET /api/persons - Récupération de toutes les personnes");

        List<PersonApi> persons = personService.getAllPersons()
                .stream()
                .map(PersonMapper::toApi)
                .collect(Collectors.toList());

        return ResponseEntity.ok(persons);
    }

    /**
     * Mettre à jour une personne
     */
    @PutMapping("/{id}")
    public ResponseEntity<PersonApi> updatePerson(
            @PathVariable Integer id,
            @Valid @RequestBody PersonApi personApi) {
        log.info("PUT /api/persons/{} - Mise à jour d'une personne", id);

        Person person = PersonMapper.toEntity(personApi);
        Person updatedPerson = personService.updatePerson(id, person);
        PersonApi response = PersonMapper.toApi(updatedPerson);

        return ResponseEntity.ok(response);
    }

    /**
     * Supprimer une personne
     */
    @DeleteMapping("/{id}")
    public ResponseEntity<Void> deletePerson(@PathVariable Integer id) {
        log.info("DELETE /api/persons/{} - Suppression d'une personne", id);

        personService.deletePerson(id);
        return ResponseEntity.noContent().build();
    }

    /**
     * Rechercher une personne par prénom et nom
     */
    @GetMapping("/search")
    public ResponseEntity<PersonApi> findByFirstNameAndLastName(
            @RequestParam String firstName,
            @RequestParam String lastName) {
        log.info("GET /api/persons/search?firstName={}&lastName={}", firstName, lastName);

        return personService.findByFirstNameAndLastName(firstName, lastName)
                .map(PersonMapper::toApi)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    /**
     * Rechercher toutes les personnes par ville
     */
    @GetMapping("/city/{city}")
    public ResponseEntity<List<PersonApi>> findByCity(@PathVariable String city) {
        log.info("GET /api/persons/city/{}", city);

        List<PersonApi> persons = personService.findByCity(city)
                .stream()
                .map(PersonMapper::toApi)
                .collect(Collectors.toList());

        return ResponseEntity.ok(persons);
    }

    /**
     * Rechercher toutes les personnes par pays
     */
    @GetMapping("/country/{country}")
    public ResponseEntity<List<PersonApi>> findByCountry(@PathVariable String country) {
        log.info("GET /api/persons/country/{}", country);

        List<PersonApi> persons = personService.findByCountry(country)
                .stream()
                .map(PersonMapper::toApi)
                .collect(Collectors.toList());

        return ResponseEntity.ok(persons);
    }

    /**
     * Gestion globale des exceptions
     */
    @ExceptionHandler(ManagePeoplesException.class)
    public ResponseEntity<ErrorResponse> handleManagePeoplesException(ManagePeoplesException ex) {
        log.error("Erreur métier: {}", ex.getMessage());
        ErrorResponse error = new ErrorResponse(ex.getMessage());
        return ResponseEntity.status(HttpStatus.BAD_REQUEST).body(error);
    }

    @ExceptionHandler(Exception.class)
    public ResponseEntity<ErrorResponse> handleException(Exception ex) {
        log.error("Erreur interne: {}", ex.getMessage(), ex);
        ErrorResponse error = new ErrorResponse("Erreur interne du serveur");
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(error);
    }

    /**
     * Classe pour les réponses d'erreur
     */
    record ErrorResponse(String message) {
    }
}
