<?php

declare(strict_types=1);

namespace App\Controllers;

require_once __DIR__ . '/../Services/PasswordSecurityService.php';
require_once __DIR__ . '/../Services/LogService.php';

use Request;
use Response;
use App\Services\LogService;
use App\Services\PasswordSecurityService;

/**
 * Contrôleur pour la gestion de la sécurité des mots de passe
 * Fournit des endpoints pour vérifier la force et la compromission des mots de passe
 */
class PasswordController {
    
    /**
     * Vérifie la force d'un mot de passe et s'il a été compromis
     * Endpoint utilisable sans authentification pour le formulaire d'inscription
     * 
     * POST /api/password/check
     */
    public function checkStrength(): void {
        try {
            $data = Request::getJson();
            
            if (!isset($data['password']) || empty($data['password'])) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Mot de passe requis'
                ], 400);
                return;
            }
            
            $password = $data['password'];
            $checkCompromised = $data['check_compromised'] ?? true;
            
            // Validation du mot de passe
            $validation = PasswordSecurityService::validatePassword($password, $checkCompromised);
            
            // Estimation de la force
            $strength = PasswordSecurityService::estimatePasswordStrength($password);
            
            // Vérification spécifique de compromission si demandée
            $compromisedInfo = null;
            if ($checkCompromised) {
                $compromisedCheck = PasswordSecurityService::checkPasswordCompromised($password);
                if ($compromisedCheck['compromised']) {
                    $compromisedInfo = [
                        'compromised' => true,
                        'occurrences' => $compromisedCheck['occurrences'],
                        'message' => sprintf(
                            'Ce mot de passe a été trouvé %s fois dans des fuites de données',
                            number_format($compromisedCheck['occurrences'], 0, ',', ' ')
                        )
                    ];
                }
            }
            
            Response::json([
                'status' => 'success',
                'valid' => $validation['valid'],
                'errors' => $validation['errors'],
                'warnings' => $validation['warnings'],
                'strength' => $strength,
                'compromised' => $compromisedInfo
            ]);
            
        } catch (\Exception $e) {
            LogService::log('Erreur lors de la vérification du mot de passe', [
                'level' => 'error',
                'error' => $e->getMessage()
            ]);
            
            Response::json([
                'status' => 'error',
                'message' => 'Erreur lors de la vérification du mot de passe'
            ], 500);
        }
    }
    
    /**
     * Génère un mot de passe sécurisé aléatoire
     * Endpoint nécessitant une authentification
     * 
     * GET /api/password/generate
     */
    public function generate(): void {
        try {
            // Vérifier l'authentification
            if (!isset($_SESSION['user_id'])) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Authentification requise'
                ], 401);
                return;
            }
            
            // Récupérer les paramètres optionnels
            $length = isset($_GET['length']) ? intval($_GET['length']) : 14;
            $length = max(12, min(20, $length)); // Limiter entre 12 et 20
            
            // Générer un mot de passe non compromis
            $password = PasswordSecurityService::generateSecurePassword($length);
            
            if ($password === null) {
                // En cas d'échec, utiliser la méthode classique
                $password = $this->generateFallbackPassword($length);
            }
            
            // Calculer la force du mot de passe généré
            $strength = PasswordSecurityService::estimatePasswordStrength($password);
            
            Response::json([
                'status' => 'success',
                'password' => $password,
                'length' => strlen($password),
                'strength' => $strength
            ]);
            
        } catch (\Exception $e) {
            LogService::log('Erreur lors de la génération du mot de passe', [
                'level' => 'error',
                'error' => $e->getMessage()
            ]);
            
            Response::json([
                'status' => 'error',
                'message' => 'Erreur lors de la génération du mot de passe'
            ], 500);
        }
    }
    
    /**
     * Vérifie uniquement si un mot de passe est compromis
     * Endpoint rapide pour vérification en temps réel
     * 
     * POST /api/password/compromised
     */
    public function checkCompromised(): void {
        try {
            $data = Request::getJson();
            
            if (!isset($data['password']) || empty($data['password'])) {
                Response::json([
                    'status' => 'error',
                    'message' => 'Mot de passe requis'
                ], 400);
                return;
            }
            
            $password = $data['password'];
            
            // Vérification de compromission
            $compromisedCheck = PasswordSecurityService::checkPasswordCompromised($password);
            
            $response = [
                'status' => 'success',
                'compromised' => $compromisedCheck['compromised'],
                'occurrences' => $compromisedCheck['occurrences']
            ];
            
            if ($compromisedCheck['compromised']) {
                $response['message'] = sprintf(
                    'Ce mot de passe a été trouvé %s fois dans des fuites de données',
                    number_format($compromisedCheck['occurrences'], 0, ',', ' ')
                );
                $response['recommendation'] = 'Il est fortement recommandé de choisir un autre mot de passe';
            }
            
            if ($compromisedCheck['error']) {
                $response['warning'] = 'Impossible de vérifier complètement le mot de passe';
            }
            
            Response::json($response);
            
        } catch (\Exception $e) {
            LogService::log('Erreur lors de la vérification de compromission', [
                'level' => 'error',
                'error' => $e->getMessage()
            ]);
            
            Response::json([
                'status' => 'error',
                'message' => 'Erreur lors de la vérification'
            ], 500);
        }
    }
    
    /**
     * Génère un mot de passe de secours si le service principal échoue
     * 
     * @param int $length Longueur du mot de passe
     * @return string Le mot de passe généré
     */
    private function generateFallbackPassword(int $length): string {
        $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()_+-=[]{}|;:,.<>?';
        $password = '';
        
        for ($i = 0; $i < $length; $i++) {
            $password .= $chars[random_int(0, strlen($chars) - 1)];
        }
        
        return $password;
    }
}