package br.gov.sigefp.api.config;

import br.gov.sigefp.admin.domain.Role;
import br.gov.sigefp.admin.domain.UserAccount;
import br.gov.sigefp.admin.domain.UserRole;
import br.gov.sigefp.admin.repository.RoleRepository;
import br.gov.sigefp.admin.repository.UserAccountRepository;
import br.gov.sigefp.admin.repository.UserRoleRepository;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.CommandLineRunner;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import java.util.Optional;

/**
 * Inicializador de dados padrão.
 * Cria usuário admin e role ADMIN se não existirem.
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class DataInitializer implements CommandLineRunner {

    private final UserAccountRepository userAccountRepository;
    private final RoleRepository roleRepository;
    private final UserRoleRepository userRoleRepository;
    private final PasswordEncoder passwordEncoder;

    @Override
    @Transactional
    public void run(String... args) {
        log.info("Inicializando dados padrão...");

        // 1. Garantir que as Roles existam
        Role adminRole = createRoleIfNtExists("ADMIN", "Administrador", "Acesso total ao sistema");
        Role hrAdminRole = createRoleIfNtExists("HR_ADMIN", "Administrador de RH",
                "Gestão completa de Recursos Humanos");
        Role hrConfigRole = createRoleIfNtExists("HR_CONFIG", "Configurador de RH",
                "Configuração de tabelas e regras de RH");

        // 2. Garantir que o usuário admin exista
        UserAccount adminUser = userAccountRepository.findByUsername("admin")
                .orElseGet(() -> {
                    log.info("Criando usuário admin padrão...");
                    UserAccount newUser = UserAccount.builder()
                            .username("admin")
                            .fullName("Administrador do Sistema")
                            .email("admin@sigefp.gov.gw")
                            .passwordHash(passwordEncoder.encode("admin123"))
                            .isActive(true)
                            .build();
                    return userAccountRepository.save(newUser);
                });

        // 3. Garantir que o admin tenha todas as roles necessárias
        assignRoleToUser(adminUser, adminRole);
        assignRoleToUser(adminUser, hrAdminRole);
        assignRoleToUser(adminUser, hrConfigRole);

        log.info("Inicialização de dados de segurança concluída.");
    }

    private Role createRoleIfNtExists(String code, String name, String description) {
        return roleRepository.findByCode(code)
                .orElseGet(() -> {
                    log.info("Criando role {}...", code);
                    Role role = Role.builder()
                            .code(code)
                            .name(name)
                            .description(description)
                            .build();
                    return roleRepository.save(role);
                });
    }

    private void assignRoleToUser(UserAccount user, Role role) {
        if (!userRoleRepository.existsByUserIdAndRoleId(user.getId(), role.getId())) {
            UserRole userRole = UserRole.builder()
                    .user(user)
                    .role(role)
                    .build();
            userRoleRepository.save(userRole);
            log.info("Role {} associada ao usuário {}.", role.getCode(), user.getUsername());
        }
    }
}
