<?php
// app/models/Professeur.php
require_once __DIR__ . '/../core/AbstractPdo.php';

class ProfesseurService extends AbstractPdo {
    protected $table = 'professeur';
    protected $primaryKey = 'id';

    public function __construct() {
        parent::__construct();
    }


    /**
     * Authenticate admin user with encrypted password
     */
    public function login($email, $password) {
        // Check if admin exists with this email
        $sql = "SELECT * FROM {$this->table} WHERE email = :email";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['email' => $email]);
        $prof = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$prof) {
            return [
                'success' => false,
                'message' => 'Email ou mot de passe incorrect'
            ];
        }

        // Check if account is blocked
        if ($prof['blocked'] == 1) {
            return [
                'success' => false,
                'message' => 'Votre compte est bloqué. Veuillez contacter l\'administrateur.'
            ];
        }

        // Verify password using password_verify()
        if (!password_verify($password, $prof['password'])) {
            // Increment failed login attempts
            $this->incrementFailedAttempts($prof['id']);

            // Check if should be blocked (3 failed attempts)
            $sql = "SELECT cnx_fail_number FROM {$this->table} WHERE id = :id";
            $stmt = $this->pdo->prepare($sql);
            $stmt->execute(['id' => $prof['id']]);
            $failCount = $stmt->fetch(PDO::FETCH_ASSOC)['cnx_fail_number'];

            if ($failCount >= 3) {
                $this->blockProf($prof['id']);
                return [
                    'success' => false,
                    'message' => 'Trop de tentatives échouées. Votre compte a été bloqué.'
                ];
            }

            return [
                'success' => false,
                'message' => 'Email ou mot de passe incorrect. Tentative ' . $failCount . '/3'
            ];
        }

        // Login successful - reset failed attempts
        $this->resetFailedAttempts($prof['id']);

        // Return admin data (without password)
        unset($prof['password']);
        $prof['success'] = true;

        return $prof;
    }


    /**
     * Update admin password with encryption
     */
    public function updatePassword($profId, $newPassword) {
        $hashedPassword = password_hash($newPassword, PASSWORD_DEFAULT);

        $sql = "UPDATE admin SET password = :password WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $result = $stmt->execute([
            'password' => $hashedPassword,
            'id' => $profId
        ]);

        if ($result) {
            return ['success' => true, 'message' => 'Mot de passe mis à jour avec succès'];
        }
        return ['success' => false, 'message' => 'Erreur lors de la mise à jour'];
    }

    /**
     * Reset admin password (admin initiated)
     */
    public function resetPassword($email, $newPassword) {
        // Verify email exists
        $sql = "SELECT id FROM {$this->table} WHERE email = :email";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['email' => $email]);
        $prof = $stmt->fetch(PDO::FETCH_ASSOC);

        if (!$prof) {
            return ['success' => false, 'message' => 'Email non trouvé'];
        }

        return $this->updatePassword($prof['id'], $newPassword);
    }

    /**
     * Check password strength
     */
    public function validatePasswordStrength($password) {
        $errors = [];

        if (strlen($password) < 8) {
            $errors[] = 'Le mot de passe doit contenir au moins 8 caractères';
        }
        if (!preg_match('/[A-Z]/', $password)) {
            $errors[] = 'Le mot de passe doit contenir au moins une majuscule';
        }
        if (!preg_match('/[a-z]/', $password)) {
            $errors[] = 'Le mot de passe doit contenir au moins une minuscule';
        }
        if (!preg_match('/[0-9]/', $password)) {
            $errors[] = 'Le mot de passe doit contenir au moins un chiffre';
        }
        if (!preg_match('/[!@#$%^&*(),.?":{}|<>]/', $password)) {
            $errors[] = 'Le mot de passe doit contenir au moins un caractère spécial';
        }

        return [
            'valid' => empty($errors),
            'errors' => $errors
        ];
    }


    /**
     * Increment failed login attempts
     */
    private function incrementFailedAttempts($profId) {
        $sql = "UPDATE {$this->table} SET cnx_fail_number = cnx_fail_number + 1 WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['id' => $profId]);
    }

    /**
     * Reset failed login attempts
     */
    private function resetFailedAttempts($profId) {
        $sql = "UPDATE {$this->table} SET cnx_fail_number = 0 WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['id' => $profId]);
    }

    /**
     * Block admin account
     */
    private function blockProf($profId) {
        $sql = "UPDATE {$this->table} SET blocked = 1 WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['id' => $profId]);
    }

    /**
     * Unblock admin account
     */
    public function unblockProf($profId) {
        $sql = "UPDATE {$this->table} SET blocked = 0, cnx_fail_number = 0 WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['id' => $profId]);
        return ['success' => true, 'message' => 'Compte débloqué avec succès'];
    }

    /**
     * Get admin by ID
     */
    public function getProfById($id) {
        $sql = "SELECT id, email, nom, prenom, cin, phone FROM {$this->table} WHERE id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute(['id' => $id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }
    /**
     * Rechercher des professeurs avec critères
     */
    public function search($searchData, $page = 1, $perPage = 10) {
        $filters = [];
        $searchFields = ['code', 'nom', 'prenom', 'email', 'cin', 'login', 'specialite', 'grade'];

        foreach ($searchFields as $field) {
            if (!empty($searchData[$field])) {
                $filters[$field] = [
                    'value' => $searchData[$field],
                    'like' => true
                ];
            }
        }

        // Filter by status
        if (isset($searchData['status']) && $searchData['status'] !== '') {
            $filters['status'] = $searchData['status'];
        }

        $offset = ($page - 1) * $perPage;
        $professeurs = $this->findMultiple($filters, 'id DESC', $perPage, $offset);
        $total = $this->count($filters);

        return [
            'data' => $professeurs,
            'total' => $total,
            'page' => $page,
            'perPage' => $perPage,
            'totalPages' => ceil($total / $perPage)
        ];
    }

    /**
     * Obtenir un professeur par ID
     */
    public function getProfesseur($id) {
        return $this->findOne($id);
    }

    /**
     * Créer un nouveau professeur
     */
    public function createProfesseur($data) {
        // Générer un code si non fourni
        if (empty($data['code'])) {
            $data['code'] = 'PR' . date('Y') . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT);
        }

        // Hasher le mot de passe
        if (!empty($data['password'])) {
            $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
        }

        // Définir les valeurs par défaut
        $data['status'] = $data['status'] ?? 'active';

        // Vérifier les doublons
        $this->checkDuplicates($data);

        return $this->insert($data);
    }

    /**
     * Mettre à jour un professeur
     */
    public function updateProfesseur($id, $data) {
        // Hasher le mot de passe si fourni
        if (!empty($data['password'])) {
            $data['password'] = password_hash($data['password'], PASSWORD_DEFAULT);
        } else {
            unset($data['password']);
        }

        // Vérifier les doublons (exclure l'ID actuel)
        $this->checkDuplicates($data, $id);

        return $this->update($id, $data);
    }

    /**
     * Vérifier les doublons
     */
    private function checkDuplicates($data, $excludeId = null) {
        $uniqueFields = ['email', 'cin', 'login'];

        foreach ($uniqueFields as $field) {
            if (isset($data[$field]) && !empty($data[$field])) {
                $criteria = [$field => $data[$field]];
                $existing = $this->findOneBy($criteria);

                if ($existing && ($excludeId === null || $existing['id'] != $excludeId)) {
                    throw new Exception("Le champ '$field' est déjà utilisé par un autre professeur");
                }
            }
        }
    }

    /**
     * Supprimer un professeur
     */
    public function deleteProfesseur($id) {
        // Vérifier si le professeur est utilisé dans des comités
        $sql = "SELECT COUNT(*) as count FROM commite_organisation_membre WHERE professeur_id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':id' => $id]);
        $result = $stmt->fetch();

        if ($result['count'] > 0) {
            throw new Exception("Ce professeur est membre d'un comité et ne peut pas être supprimé");
        }

        // Vérifier si le professeur est chef de comité
        $sql = "SELECT COUNT(*) as count FROM commite_organisation WHERE chef_id = :id";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':id' => $id]);
        $result = $stmt->fetch();

        if ($result['count'] > 0) {
            throw new Exception("Ce professeur est chef d'un comité et ne peut pas être supprimé");
        }

        return $this->delete($id);
    }

    /**
     * Obtenir les statistiques
     */
    public function getStats() {
        $sql = "SELECT 
                    COUNT(*) as total,
                    SUM(CASE WHEN status = 'active' THEN 1 ELSE 0 END) as actif,
                    SUM(CASE WHEN status = 'inactive' THEN 1 ELSE 0 END) as inactif
                FROM {$this->table}";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute();
        return $stmt->fetch();
    }

    /**
     * Obtenir les professeurs par grade
     */
    public function getByGrade($grade) {
        return $this->findMultiple(['grade' => $grade]);
    }

    /**
     * Obtenir les professeurs disponibles (non membres d'un comité)
     */
    public function getAvailableProfessors($committeeId = null) {
        $sql = "SELECT p.* FROM {$this->table} p 
                WHERE p.status = 'active' 
                AND p.id NOT IN (
                    SELECT professeur_id FROM commite_organisation_membre 
                    WHERE commite_organisation_id != :committeeId OR :committeeId IS NULL
                )";
        $stmt = $this->pdo->prepare($sql);
        $stmt->execute([':committeeId' => $committeeId]);
        return $stmt->fetchAll();
    }

    /**
     * Authentifier un professeur
     */
    public function authenticate($login, $password) {
        $professeur = $this->findOneBy(['login' => $login]);

        if (!$professeur) {
            return ['success' => false, 'message' => 'Login ou mot de passe incorrect'];
        }

        if ($professeur['status'] !== 'active') {
            return ['success' => false, 'message' => 'Compte désactivé'];
        }

        if (!password_verify($password, $professeur['password'])) {
            return ['success' => false, 'message' => 'Login ou mot de passe incorrect'];
        }

        // Mettre à jour la dernière connexion
        $this->update($professeur['id'], ['last_login' => date('Y-m-d H:i:s')]);

        unset($professeur['password']);

        return ['success' => true, 'user' => $professeur];
    }

    /**
     * Exporter les professeurs (CSV)
     */
    public function exportToCsv() {
        $professeurs = $this->findAll('code ASC');

        if (empty($professeurs)) {
            return null;
        }

        $csv = "Code,Nom,Prénom,CIN,Email,Login,Téléphone,Spécialité,Grade,Statut\n";
        foreach ($professeurs as $p) {
            $csv .= implode(',', [
                    $p['code'],
                    $p['nom'],
                    $p['prenom'],
                    $p['cin'],
                    $p['email'],
                    $p['login'],
                    $p['phone'] ?? '',
                    $p['specialite'] ?? '',
                    $p['grade'] ?? '',
                    $p['status']
                ]) . "\n";
        }

        return $csv;
    }

    /**
     * Importer des professeurs (CSV)
     */
    public function importFromCsv($csvData) {
        $lines = explode("\n", trim($csvData));
        $headers = str_getcsv(array_shift($lines));

        $imported = 0;
        $errors = [];

        foreach ($lines as $line) {
            if (empty(trim($line))) continue;

            $data = array_combine($headers, str_getcsv($line));

            try {
                // Vérifier si le code existe déjà
                $existing = $this->findOneBy(['code' => $data['Code']]);
                if ($existing) {
                    // Mettre à jour
                    $this->update($existing['id'], [
                        'nom' => $data['Nom'],
                        'prenom' => $data['Prénom'],
                        'cin' => $data['CIN'],
                        'email' => $data['Email'],
                        'login' => $data['Login'],
                        'phone' => $data['Téléphone'] ?? null,
                        'specialite' => $data['Spécialité'] ?? null,
                        'grade' => $data['Grade'] ?? null,
                        'status' => $data['Statut'] ?? 'active'
                    ]);
                } else {
                    // Créer
                    $this->createProfesseur([
                        'code' => $data['Code'],
                        'nom' => $data['Nom'],
                        'prenom' => $data['Prénom'],
                        'cin' => $data['CIN'],
                        'email' => $data['Email'],
                        'login' => $data['Login'],
                        'password' => 'default123', // Mot de passe par défaut
                        'phone' => $data['Téléphone'] ?? null,
                        'specialite' => $data['Spécialité'] ?? null,
                        'grade' => $data['Grade'] ?? null,
                        'status' => $data['Statut'] ?? 'active'
                    ]);
                }
                $imported++;
            } catch (Exception $e) {
                $errors[] = "Erreur ligne " . ($imported + 1) . ": " . $e->getMessage();
            }
        }

        return [
            'imported' => $imported,
            'errors' => $errors
        ];
    }
}
?>
