DataInitializer.java

package com.archiweb.config;

import com.archiweb.model.*;
import com.archiweb.repository.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.CommandLineRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.crypto.password.PasswordEncoder;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

@Configuration
public class DataInitializer {

    // 📥 Lecture des comptes depuis application.properties
    @Value("${admin.email}")
    private String adminEmail;

    @Value("${admin.username}")
    private String adminUsername;

    @Value("${admin.password}")
    private String adminPassword;

    @Value("${employee.email}")
    private String employeeEmail;

    @Value("${employee.username}")
    private String employeeUsername;

    @Value("${employee.password}")
    private String employeePassword;

    @Value("${user.email}")
    private String userEmail;

    @Value("${user.username}")
    private String userUsername;

    @Value("${user.password}")
    private String userPassword;

    @Bean
    CommandLineRunner initDatabase(
            RoleRepository roleRepo,
            UserRepository userRepo,
            CodeRepository codeRepo,
            ParticipationRepository participationRepo,
            WinRepository winRepo,
            PasswordEncoder encoder) {
        return args -> {
            // 🧩 Création des rôles
            Role adminRole = roleRepo.findByName("ROLE_ADMIN")
                    .orElseGet(() -> roleRepo.save(new Role(null, "ROLE_ADMIN", "Rôle administrateur. Accès complet à toutes les fonctionnalités d'administration du système.", true)));
            Role userRole = roleRepo.findByName("ROLE_USER")
                    .orElseGet(() -> roleRepo.save(new Role(null, "ROLE_USER", "Rôle utilisateur standard. Permet de participer au jeu concours et de consulter son profil.", true)));
            Role employeeRole = roleRepo.findByName("ROLE_EMPLOYEE")
                    .orElseGet(() -> roleRepo.save(new Role(null, "ROLE_EMPLOYEE", "Rôle employé boutique. Permet de vérifier un code scanné ou saisi par un client, confirmer qu'un lot a été remis en boutique, et marquer un gain comme distribué dans le système. Accès uniquement à la vérification des lots, pas aux statistiques globales.", true)));

            System.out.println("✅ Rôles vérifiés/créés : ADMIN, USER, EMPLOYEE");

            // 👑 Administrateur
            User admin = userRepo.findByEmail(adminEmail).orElse(null);
            if (admin == null) {
                admin = new User();
                admin.setUsername(adminUsername);
                admin.setEmail(adminEmail);
                admin.setPassword(encoder.encode(adminPassword));
                admin.setRole(adminRole);
                admin.setFirstName("Karim");
                admin.setLastName("Ait Bouaddi");
                admin.setActive(true);
                admin.setConsentGiven(true);
                admin = userRepo.save(admin);
                System.out.println("✅ Administrateur créé : " + adminEmail);
            } else {
                System.out.println("ℹ️ Administrateur déjà existant : " + adminEmail);
            }

            // 🧰 Employé
            User employee = userRepo.findByEmail(employeeEmail).orElse(null);
            if (employee == null) {
                employee = new User();
                employee.setUsername(employeeUsername);
                employee.setEmail(employeeEmail);
                employee.setPassword(encoder.encode(employeePassword));
                employee.setRole(employeeRole);
                employee.setFirstName("Marie");
                employee.setLastName("Dupont");
                employee.setActive(true);
                employee.setConsentGiven(true);
                employee = userRepo.save(employee);
                System.out.println("✅ Employé créé : " + employeeEmail);
            } else {
                System.out.println("ℹ️ Employé déjà existant : " + employeeEmail);
            }

            // 🙋 Utilisateurs de démo
            List<User> demoUsers = new ArrayList<>();
            
            // Utilisateur 1
            User user1 = userRepo.findByEmail(userEmail).orElse(null);
            if (user1 == null) {
                user1 = new User();
                user1.setUsername(userUsername);
                user1.setEmail(userEmail);
                user1.setPassword(encoder.encode(userPassword));
                user1.setRole(userRole);
                user1.setFirstName("Jean");
                user1.setLastName("Martin");
                user1.setActive(true);
                user1.setConsentGiven(true);
                user1 = userRepo.save(user1);
                System.out.println("✅ Utilisateur créé : " + userEmail);
            } else {
                System.out.println("ℹ️ Utilisateur déjà existant : " + userEmail);
            }
            demoUsers.add(user1);

            // Utilisateur 2
            User user2 = userRepo.findByEmail("sophie.bernard@example.com").orElse(null);
            if (user2 == null) {
                user2 = new User();
                user2.setUsername("sophie.bernard");
                user2.setEmail("sophie.bernard@example.com");
                user2.setPassword(encoder.encode("demo123"));
                user2.setRole(userRole);
                user2.setFirstName("Sophie");
                user2.setLastName("Bernard");
                user2.setActive(true);
                user2.setConsentGiven(true);
                user2 = userRepo.save(user2);
                System.out.println("✅ Utilisateur de démo créé : sophie.bernard@example.com");
            }
            demoUsers.add(user2);

            // Utilisateur 3
            User user3 = userRepo.findByEmail("pierre.durand@example.com").orElse(null);
            if (user3 == null) {
                user3 = new User();
                user3.setUsername("pierre.durand");
                user3.setEmail("pierre.durand@example.com");
                user3.setPassword(encoder.encode("demo123"));
                user3.setRole(userRole);
                user3.setFirstName("Pierre");
                user3.setLastName("Durand");
                user3.setActive(true);
                user3.setConsentGiven(true);
                user3 = userRepo.save(user3);
                System.out.println("✅ Utilisateur de démo créé : pierre.durand@example.com");
            }
            demoUsers.add(user3);

            // Utilisateur 4
            User user4 = userRepo.findByEmail("lucie.moreau@example.com").orElse(null);
            if (user4 == null) {
                user4 = new User();
                user4.setUsername("lucie.moreau");
                user4.setEmail("lucie.moreau@example.com");
                user4.setPassword(encoder.encode("demo123"));
                user4.setRole(userRole);
                user4.setFirstName("Lucie");
                user4.setLastName("Moreau");
                user4.setActive(true);
                user4.setConsentGiven(true);
                user4 = userRepo.save(user4);
                System.out.println("✅ Utilisateur de démo créé : lucie.moreau@example.com");
            }
            demoUsers.add(user4);

            // Utilisateur 5
            User user5 = userRepo.findByEmail("thomas.lefebvre@example.com").orElse(null);
            if (user5 == null) {
                user5 = new User();
                user5.setUsername("thomas.lefebvre");
                user5.setEmail("thomas.lefebvre@example.com");
                user5.setPassword(encoder.encode("demo123"));
                user5.setRole(userRole);
                user5.setFirstName("Thomas");
                user5.setLastName("Lefebvre");
                user5.setActive(true);
                user5.setConsentGiven(true);
                user5 = userRepo.save(user5);
                System.out.println("✅ Utilisateur de démo créé : thomas.lefebvre@example.com");
            }
            demoUsers.add(user5);

            // 🎫 Création de codes de démo
            System.out.println("\n🎫 Création des codes de démo...");
            List<Code> demoCodes = new ArrayList<>();
            
            // Codes gagnants
            String[] winningCodes = {
                "DEMO001WIN", "DEMO002WIN", "DEMO003WIN", "DEMO004WIN", "DEMO005WIN"
            };
            PrizeType[] winningPrizes = {
                PrizeType.INFUSEUR, PrizeType.DETOX_100G, PrizeType.SIGNATURE_100G,
                PrizeType.COFFRET_39, PrizeType.COFFRET_69
            };
            
            for (int i = 0; i < winningCodes.length; i++) {
                Code code = codeRepo.findByValeur(winningCodes[i]).orElse(null);
                if (code == null) {
                    code = Code.builder()
                        .valeur(winningCodes[i])
                        .prizeType(winningPrizes[i])
                        .gagnant(true)
                        .used(false)
                        .expiresAt(LocalDateTime.now().plusMonths(6))
                        .build();
                    code = codeRepo.save(code);
                    demoCodes.add(code);
                    System.out.println("✅ Code gagnant créé : " + winningCodes[i] + " -> " + winningPrizes[i]);
                }
            }

            // Codes non gagnants
            for (int i = 1; i <= 20; i++) {
                String codeValue = "DEMO" + String.format("%03d", i) + "LOSE";
                Code code = codeRepo.findByValeur(codeValue).orElse(null);
                if (code == null) {
                    code = Code.builder()
                        .valeur(codeValue)
                        .prizeType(PrizeType.INFUSEUR) // Type par défaut pour les codes perdants
                        .gagnant(false)
                        .used(false)
                        .expiresAt(LocalDateTime.now().plusMonths(6))
                        .build();
                    code = codeRepo.save(code);
                    demoCodes.add(code);
                }
            }
            System.out.println("✅ 20 codes non gagnants créés");

            // 🎁 Création de participations et gains
            System.out.println("\n🎁 Création des participations et gains...");
            
            // Participation 1 : User1 gagne un INFUSEUR
            if (demoCodes.size() > 0) {
                Code code1 = demoCodes.get(0);
                Participation participation1 = new Participation();
                participation1.setUser(user1);
                participation1.setCode(code1);
                participation1.setPrizeName("Infuseur à thé");
                participation1.setClaimed(true);
                participation1.setClaimedAt(LocalDateTime.now().minusDays(5));
                participation1.setClaimChannel("boutique");
                participation1 = participationRepo.save(participation1);
                
                Win win1 = Win.builder()
                    .user(user1)
                    .prizeName("Infuseur à thé")
                    .claimed(true)
                    .createdAt(LocalDateTime.now().minusDays(5))
                    .claimedAt(LocalDateTime.now().minusDays(3))
                    .build();
                winRepo.save(win1);
                System.out.println("✅ Participation et gain créés pour " + user1.getEmail() + " : Infuseur à thé");
            }

            // Participation 2 : User2 gagne un DETOX_100G
            if (demoCodes.size() > 1) {
                Code code2 = demoCodes.get(1);
                Participation participation2 = new Participation();
                participation2.setUser(user2);
                participation2.setCode(code2);
                participation2.setPrizeName("Thé DETOX 100g");
                participation2.setClaimed(false);
                participation2 = participationRepo.save(participation2);
                
                Win win2 = Win.builder()
                    .user(user2)
                    .prizeName("Thé DETOX 100g")
                    .claimed(false)
                    .createdAt(LocalDateTime.now().minusDays(3))
                    .build();
                winRepo.save(win2);
                System.out.println("✅ Participation et gain créés pour " + user2.getEmail() + " : Thé DETOX 100g (non réclamé)");
            }

            // Participation 3 : User3 gagne un SIGNATURE_100G
            if (demoCodes.size() > 2) {
                Code code3 = demoCodes.get(2);
                Participation participation3 = new Participation();
                participation3.setUser(user3);
                participation3.setCode(code3);
                participation3.setPrizeName("Thé SIGNATURE 100g");
                participation3.setClaimed(true);
                participation3.setClaimedAt(LocalDateTime.now().minusDays(2));
                participation3.setClaimChannel("domicile");
                participation3 = participationRepo.save(participation3);
                
                Win win3 = Win.builder()
                    .user(user3)
                    .prizeName("Thé SIGNATURE 100g")
                    .claimed(true)
                    .createdAt(LocalDateTime.now().minusDays(2))
                    .claimedAt(LocalDateTime.now().minusDays(1))
                    .build();
                winRepo.save(win3);
                System.out.println("✅ Participation et gain créés pour " + user3.getEmail() + " : Thé SIGNATURE 100g");
            }

            // Participation 4 : User4 gagne un COFFRET_39
            if (demoCodes.size() > 3) {
                Code code4 = demoCodes.get(3);
                Participation participation4 = new Participation();
                participation4.setUser(user4);
                participation4.setCode(code4);
                participation4.setPrizeName("Coffret cadeau 39€");
                participation4.setClaimed(false);
                participation4 = participationRepo.save(participation4);
                
                Win win4 = Win.builder()
                    .user(user4)
                    .prizeName("Coffret cadeau 39€")
                    .claimed(false)
                    .createdAt(LocalDateTime.now().minusDays(1))
                    .build();
                winRepo.save(win4);
                System.out.println("✅ Participation et gain créés pour " + user4.getEmail() + " : Coffret cadeau 39€ (non réclamé)");
            }

            // Participation 5 : User5 gagne un COFFRET_69
            if (demoCodes.size() > 4) {
                Code code5 = demoCodes.get(4);
                Participation participation5 = new Participation();
                participation5.setUser(user5);
                participation5.setCode(code5);
                participation5.setPrizeName("Coffret cadeau 69€");
                participation5.setClaimed(true);
                participation5.setClaimedAt(LocalDateTime.now().minusHours(12));
                participation5.setClaimChannel("boutique");
                participation5 = participationRepo.save(participation5);
                
                Win win5 = Win.builder()
                    .user(user5)
                    .prizeName("Coffret cadeau 69€")
                    .claimed(true)
                    .createdAt(LocalDateTime.now().minusDays(1))
                    .claimedAt(LocalDateTime.now().minusHours(12))
                    .build();
                winRepo.save(win5);
                System.out.println("✅ Participation et gain créés pour " + user5.getEmail() + " : Coffret cadeau 69€");
            }

            // Quelques participations perdantes
            for (int i = 5; i < Math.min(10, demoCodes.size()); i++) {
                Code code = demoCodes.get(i);
                if (!code.isGagnant()) {
                    Participation participation = new Participation();
                    participation.setUser(demoUsers.get(i % demoUsers.size()));
                    participation.setCode(code);
                    participation.setPrizeName("Aucun lot");
                    participation.setClaimed(false);
                    participationRepo.save(participation);
                }
            }
            System.out.println("✅ Participations perdantes créées");

            System.out.println("\n🚀 Initialisation des données de démo terminée !");
            System.out.println("📊 Résumé :");
            System.out.println("   - " + demoUsers.size() + " utilisateurs de démo");
            System.out.println("   - " + demoCodes.size() + " codes créés");
            System.out.println("   - 5 gains créés avec différents statuts");
            System.out.println("   - Participations créées pour la démo");
        };
    }
}