package sn.ladoum.bergerie.controller;

import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import sn.ladoum.bergerie.dto.MoutonDto;
import sn.ladoum.bergerie.entity.enums.Sexe;
import sn.ladoum.bergerie.entity.enums.StatutMouton;
import sn.ladoum.bergerie.qr.QrCodeService;
import sn.ladoum.bergerie.service.MoutonService;

import java.util.List;

@RestController
@RequestMapping("/moutons")
@RequiredArgsConstructor
public class MoutonController {

    private final MoutonService moutonService;
    private final QrCodeService qrCodeService;

    @Value("${app.frontend.base-url}")
    private String frontendBaseUrl;

    @GetMapping
    public List<MoutonDto> getAll() {
        return moutonService.findAll();
    }

    @GetMapping("/{id}")
    public MoutonDto getById(@PathVariable Long id) {
        return moutonService.findById(id);
    }

    @PostMapping
    @PreAuthorize("hasAnyRole('ADMIN','ELEVEUR')")
    @ResponseStatus(HttpStatus.CREATED)
    public MoutonDto create(@Valid @RequestBody MoutonDto dto) {
        return moutonService.create(dto);
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasAnyRole('ADMIN','ELEVEUR')")
    public MoutonDto update(@PathVariable Long id, @Valid @RequestBody MoutonDto dto) {
        return moutonService.update(id, dto);
    }

    @PostMapping(value = "/{id}/photo", consumes = "multipart/form-data")
    @PreAuthorize("hasAnyRole('ADMIN','ELEVEUR')")
    public MoutonDto uploadPhoto(@PathVariable Long id, @RequestParam("file") MultipartFile file) {
        return moutonService.uploadPhoto(id, file);
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<Void> delete(@PathVariable Long id) {
        moutonService.delete(id);
        return ResponseEntity.noContent().build();
    }

    @GetMapping("/search")
    public List<MoutonDto> search(@RequestParam String nom) {
        return moutonService.searchByNom(nom);
    }

    @GetMapping("/sexe/{sexe}")
    public List<MoutonDto> bySexe(@PathVariable Sexe sexe) {
        return moutonService.findBySexe(sexe);
    }

    @GetMapping("/statut/{statut}")
    public List<MoutonDto> byStatut(@PathVariable StatutMouton statut) {
        return moutonService.findByStatut(statut);
    }

    /** Pool public de reproducteurs mâles (toutes bergeries) pour enregistrer une naissance. */
    @GetMapping("/reproducteurs/males")
    public List<MoutonDto> reproducteursMales() {
        return moutonService.listReproducteursMales();
    }

    /** Pool public de femelles vivantes (toutes bergeries) pour renseigner une mère. */
    @GetMapping("/reproductrices/femelles")
    public List<MoutonDto> reproductricesFemelles() {
        return moutonService.listReproductricesFemelles();
    }

    /**
     * Fiche publique d'un mouton — accessible à tout utilisateur authentifié,
     * sans filtre de propriété. Cible du QR code.
     */
    @GetMapping("/{id}/public-info")
    public MoutonDto publicInfo(@PathVariable Long id) {
        return moutonService.findPublicInfo(id);
    }

    /** Descendance directe (enfants) d'un mouton — accessible à tout utilisateur authentifié. */
    @GetMapping("/{id}/descendance")
    public List<MoutonDto> descendance(@PathVariable Long id) {
        return moutonService.descendanceDirecte(id);
    }

    /** QR code PNG pointant vers la fiche publique du mouton. */
    @GetMapping(value = "/{id}/qrcode", produces = MediaType.IMAGE_PNG_VALUE)
    public ResponseEntity<byte[]> qrCode(@PathVariable Long id,
                                         @RequestParam(defaultValue = "320") int size) {
        // On vérifie que le mouton existe (404 propre sinon)
        MoutonDto m = moutonService.findPublicInfo(id);
        String url = frontendBaseUrl + "/moutons/" + m.getId() + "/public";
        byte[] png = qrCodeService.generatePng(url, size);
        return ResponseEntity.ok()
                .header(HttpHeaders.CONTENT_DISPOSITION,
                        "inline; filename=\"qrcode-mouton-" + m.getId() + ".png\"")
                .contentType(MediaType.IMAGE_PNG)
                .body(png);
    }
}
