package sn.ladoum.bergerie.auth;

import lombok.RequiredArgsConstructor;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import sn.ladoum.bergerie.auth.dto.AuthResponse;
import sn.ladoum.bergerie.auth.dto.LoginRequest;
import sn.ladoum.bergerie.auth.dto.RegisterRequest;
import sn.ladoum.bergerie.entity.Utilisateur;
import sn.ladoum.bergerie.entity.enums.Role;
import sn.ladoum.bergerie.repository.UtilisateurRepository;
import sn.ladoum.bergerie.security.CustomUserDetailsService;
import sn.ladoum.bergerie.security.JwtService;
import sn.ladoum.bergerie.storage.FileStorageService;
import org.springframework.security.crypto.password.PasswordEncoder;

@Service
@RequiredArgsConstructor
public class AuthService {

    private final UtilisateurRepository utilisateurRepository;
    private final PasswordEncoder passwordEncoder;
    private final JwtService jwtService;
    private final CustomUserDetailsService userDetailsService;
    private final FileStorageService fileStorageService;

    @Transactional
    public AuthResponse register(RegisterRequest request, MultipartFile logo) {
        if (logo == null || logo.isEmpty()) {
            throw new IllegalArgumentException("Le logo de la bergerie est obligatoire.");
        }
        if (utilisateurRepository.existsByEmail(request.getEmail())) {
            throw new IllegalArgumentException("Un utilisateur existe déjà avec cet email.");
        }
        String telephone = request.getTelephone() != null ? request.getTelephone().trim() : "";
        if (telephone.isEmpty()) {
            throw new IllegalArgumentException("Le téléphone est obligatoire.");
        }
        if (utilisateurRepository.existsByTelephone(telephone)) {
            throw new IllegalArgumentException("Un utilisateur existe déjà avec ce téléphone.");
        }

        String nomBergerie = request.getNomBergerie() != null ? request.getNomBergerie().trim() : "";
        if (nomBergerie.isEmpty()) {
            throw new IllegalArgumentException("Le nom de la bergerie est obligatoire.");
        }
        if (utilisateurRepository.existsByNomBergerieIgnoreCase(nomBergerie)) {
            throw new IllegalArgumentException(
                    "Une bergerie porte déjà ce nom (" + nomBergerie + "). Choisissez un autre nom.");
        }

        String logoUrl = fileStorageService.store(logo, "logos");

        Utilisateur user = Utilisateur.builder()
                .nom(request.getNom())
                .email(request.getEmail())
                .motDePasse(passwordEncoder.encode(request.getMotDePasse()))
                .role(Role.ELEVEUR)
                .actif(false)
                .nomBergerie(nomBergerie)
                .logo(logoUrl)
                .adresse(request.getAdresse())
                .telephone(telephone)
                .build();
        utilisateurRepository.save(user);

        return AuthResponse.builder()
                .token(null)
                .email(user.getEmail())
                .nom(user.getNom())
                .role(user.getRole())
                .build();
    }

    public AuthResponse login(LoginRequest request) {
        Utilisateur user = utilisateurRepository.findByTelephone(request.getTelephone())
                .orElseThrow(() -> new BadCredentialsException("Téléphone ou mot de passe incorrect"));

        if (!passwordEncoder.matches(request.getMotDePasse(), user.getMotDePasse())) {
            throw new BadCredentialsException("Téléphone ou mot de passe incorrect");
        }
        if (!Boolean.TRUE.equals(user.getActif())) {
            throw new DisabledException("Compte en attente d'activation par un administrateur.");
        }

        UserDetails details = userDetailsService.loadUserByUsername(user.getEmail());
        String token = jwtService.generateToken(details);
        return AuthResponse.builder()
                .token(token)
                .email(user.getEmail())
                .nom(user.getNom())
                .role(user.getRole())
                .build();
    }
}
