package fr.eni.enchere.dal;

import fr.eni.enchere.bo.UserProfil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Primary;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.support.GeneratedKeyHolder;
import org.springframework.jdbc.support.KeyHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Repository;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.List;

@Repository
@Primary
public class UserRepositoryImpl implements UserRepository {

    private final JdbcTemplate jdbcTemplate;
    private NamedParameterJdbcTemplate namedParameterJdbcTemplate;
    private PasswordEncoder passwordEncoder;

    @Autowired
    public UserRepositoryImpl(JdbcTemplate jdbcTemplate, NamedParameterJdbcTemplate namedJdbcTemplate, PasswordEncoder passwordEncoder) {
        this.jdbcTemplate = jdbcTemplate;
        this.namedParameterJdbcTemplate = namedJdbcTemplate;
        this.passwordEncoder = passwordEncoder;
    }

    public class UserRowMapper implements RowMapper<UserProfil> {

        @Override
        public UserProfil mapRow(ResultSet rs, int rowNum) throws SQLException {
                UserProfil userProfile = new UserProfil();
                userProfile.setId(rs.getInt("no_utilisateur"));
                userProfile.setPrenom(rs.getString("prenom"));
                userProfile.setNom(rs.getString("nom"));
                userProfile.setPseudo(rs.getString("pseudo"));
                userProfile.setEmail(rs.getString("email"));
                userProfile.setTelephone(rs.getString("telephone"));
                userProfile.setRue(rs.getString("rue"));
                userProfile.setCode_postal(rs.getString("code_postal"));
                userProfile.setVille(rs.getString("ville"));
                userProfile.setPassword(rs.getString("mot_de_passe"));
                userProfile.setCredit(rs.getFloat("credit"));
                userProfile.setAdmin(rs.getBoolean("administrateur"));
                userProfile.setDisabled(rs.getBoolean("isDisabled"));
                return userProfile;
        }
    }

    @Override
    public UserProfil findByUsername(String username) {
        String sql = "SELECT * FROM UTILISATEURS WHERE (pseudo = ? OR email = ?) AND isDelete = 0 AND isDisabled = 0";
        UserProfil user = jdbcTemplate.queryForObject(sql, new UserRowMapper(), username, username);
        return user;
    }

    @Override
    public UserProfil findUserByEmail(String email) {
        String sql = "SELECT * FROM UTILISATEURS WHERE email = ? AND isDelete = 0";
        UserProfil user = jdbcTemplate.queryForObject(sql, new UserRowMapper(), email);
        return user;
    }

    @Override
    public List<String> findAllUsernames() {
        String sql = "SELECT pseudo FROM UTILISATEURS WHERE isDelete = 0 ";
        List<String> usernames = jdbcTemplate.queryForList(sql, String.class);
        return usernames;
    }

    @Override
    public List<String> findAllEmail() {
        String sql = "SELECT email FROM UTILISATEURS WHERE isDelete = 0";
        List<String> email = jdbcTemplate.queryForList(sql, String.class);
        return email;
    }

    @Override
    public String findByEmail(String email) {
        //Vérifie si un email existe dans la base et est valide
        String sql = "SELECT email FROM UTILISATEURS WHERE email = ? AND isDelete = 0";
        try {
            return jdbcTemplate.queryForObject(sql, new Object[]{email}, String.class);
        } catch (EmptyResultDataAccessException e) {
            // Aucun résultat trouvé, retourne null
            return null;
        }
    }

    @Override
    public List<UserProfil> findAll() {
        String sql = "SELECT * FROM UTILISATEURS WHERE isDelete = 0";
        List<UserProfil> users = jdbcTemplate.query(sql, new UserRowMapper());
        return users;
    }

    @Override
    public UserProfil findById(int id) {
        String sql = "SELECT * FROM UTILISATEURS WHERE no_utilisateur = ? AND isDelete = 0";
        UserProfil user = jdbcTemplate.queryForObject(sql, new UserRowMapper(), id);
        return user;
    }

    @Override
    public void save(UserProfil utilisateur) {
        if (utilisateur.getId() == 0) {
            //Création utilisateur
            String sql = "INSERT INTO UTILISATEURS (pseudo, nom, prenom, email, telephone, rue, code_postal, ville, mot_de_passe, credit, administrateur, isDisabled, isDelete) " +
                    "VALUES (:pseudo, :nom, :prenom, :email, :telephone, :rue, :code_postal, :ville, :mot_de_passe, 0, false, false, false)";
            MapSqlParameterSource parameters = new MapSqlParameterSource();
            parameters.addValue("pseudo", utilisateur.getPseudo());
            parameters.addValue("nom", utilisateur.getNom());
            parameters.addValue("prenom", utilisateur.getPrenom());
            parameters.addValue("email", utilisateur.getEmail());
            parameters.addValue("telephone", utilisateur.getTelephone());
            parameters.addValue("rue", utilisateur.getRue());
            parameters.addValue("code_postal", utilisateur.getCode_postal());
            parameters.addValue("ville", utilisateur.getVille());
            parameters.addValue("mot_de_passe", passwordEncoder.encode(utilisateur.getPassword()));
            KeyHolder keyHolder = new GeneratedKeyHolder();
            namedParameterJdbcTemplate.update(sql, parameters, keyHolder, new String[] {"no_utilisateur"});
            if (keyHolder.getKey() != null) {
                utilisateur.setId(keyHolder.getKey().intValue());
            }
        }else {
            //Mettre à jour
            String sql;
            MapSqlParameterSource parameters = new MapSqlParameterSource();
            if(utilisateur.getNewPassword().isEmpty()){
                sql = "UPDATE UTILISATEURS SET pseudo = :pseudo, nom = :nom, prenom = :prenom, email = :email, telephone = :telephone, rue = :rue, code_postal = :code_postal, ville = :ville " +
                        "WHERE no_utilisateur = :id";
            }else{
                sql = "UPDATE UTILISATEURS SET pseudo = :pseudo, nom = :nom, prenom = :prenom, email = :email, telephone = :telephone, rue = :rue, code_postal = :code_postal," +
                        " ville = :ville, mot_de_passe = :mot_de_passe WHERE no_utilisateur = :id";
                parameters.addValue("mot_de_passe", passwordEncoder.encode(utilisateur.getNewPassword()));
            }
            parameters.addValue("pseudo", utilisateur.getPseudo());
            parameters.addValue("nom", utilisateur.getNom());
            parameters.addValue("prenom", utilisateur.getPrenom());
            parameters.addValue("email", utilisateur.getEmail());
            parameters.addValue("telephone", utilisateur.getTelephone());
            parameters.addValue("rue", utilisateur.getRue());
            parameters.addValue("code_postal", utilisateur.getCode_postal());
            parameters.addValue("ville", utilisateur.getVille());
            parameters.addValue("mot_de_passe", passwordEncoder.encode(utilisateur.getNewPassword())); // Assurez-vous de hasher le nouveau mot de passe si nécessaire
            parameters.addValue("id", utilisateur.getId());
            namedParameterJdbcTemplate.update(sql, parameters);
        }
    }

    @Override
    public void updateCredit(float credit, int id) {
        String sql = "UPDATE UTILISATEURS SET credit = ? WHERE no_utilisateur = ?";
        jdbcTemplate.update(sql, credit, id);
    }

    @Override
    public void delete(int id) {
        String sql = "UPDATE UTILISATEURS SET isDelete = 1 WHERE no_utilisateur = ?";
        jdbcTemplate.update(sql, id);
    }

    @Override
    public void disable(int id) {
        String sql = "UPDATE UTILISATEURS SET isDisabled = 1 WHERE no_utilisateur = ?";
        jdbcTemplate.update(sql, id);
    }

    @Override
    public void enable(int id) {
        String sql = "UPDATE UTILISATEURS SET isDisabled = 0 WHERE no_utilisateur = ?";
        jdbcTemplate.update(sql, id);
    }

    @Override
    public void onAdmin(int id) {
        String sql = "UPDATE UTILISATEURS SET administrateur = 1 WHERE no_utilisateur = ?";
        jdbcTemplate.update(sql, id);
    }

    @Override
    public void offAdmin(int id) {
        String sql = "UPDATE UTILISATEURS SET administrateur = 0 WHERE no_utilisateur = ?";
        jdbcTemplate.update(sql, id);
    }

}