<?php
namespace App\Controllers;

use App\Core\Controller;
use App\Core\Database;
use App\Core\Mailer;
use App\Core\Config;
use PDO;

class PasswordController extends Controller
{
    public function forgot(): void
    {
        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
            $email = trim($_POST['email'] ?? '');
            $pdo = Database::pdo();
            $this->ensurePasswordResetsTable($pdo);

            // Recherche utilisateur actif par email
            $stmt = $pdo->prepare('SELECT id, name, email FROM users WHERE email = ? AND active = 1 LIMIT 1');
            $stmt->execute([$email]);
            $user = $stmt->fetch(PDO::FETCH_ASSOC);

            // Toujours répondre succès (ne pas divulguer existence)
            if ($user) {
                try {
                    // Générer un token aléatoire et stocker son hash
                    $token = bin2hex(random_bytes(32));
                    $hash = hash('sha256', $token);
                    $ins = $pdo->prepare('INSERT INTO password_resets (user_id, token_hash, expires_at, created_at) VALUES (?,?, DATE_ADD(NOW(), INTERVAL 1 HOUR), NOW())');
                    $ins->execute([(int)$user['id'], $hash]);

                    // Construire lien sécurisé
                    $base = rtrim(Config::baseUrl(), '/');
                    $link = $base . '/password/reset?uid=' . (int)$user['id'] . '&token=' . urlencode($token);

                    // Envoyer l'email
                    $subject = 'Réinitialisation de votre mot de passe';
                    $body = '<p>Bonjour ' . htmlspecialchars($user['name'] ?: 'Utilisateur') . ',</p>'
                        . '<p>Vous avez demandé à réinitialiser votre mot de passe. Cliquez sur le lien ci-dessous (valide 1 heure) :</p>'
                        . '<p><a href="' . htmlspecialchars($link) . '">Réinitialiser mon mot de passe</a></p>'
                        . '<p>Si vous n\'êtes pas à l\'origine de cette demande, vous pouvez ignorer cet email.</p>'
                        . '<p>Cordialement,<br>' . htmlspecialchars(Config::get('app_name', 'NOVALINK')) . '</p>';
                    Mailer::send($user['email'], $user['name'] ?: 'Utilisateur', $subject, $body, $pdo);
                } catch (\Throwable $e) {
                    // Ignorer pour ne pas divulguer
                }
            }

            $this->view('auth/forgot', ['sent' => true, '_layout' => 'auth']);
            return;
        }
        $this->view('auth/forgot', ['_layout' => 'auth']);
    }

    public function reset(): void
    {
        $pdo = Database::pdo();
        $this->ensurePasswordResetsTable($pdo);

        $uid = (int)($_GET['uid'] ?? $_POST['uid'] ?? 0);
        $token = trim($_GET['token'] ?? $_POST['token'] ?? '');

        if (($_SERVER['REQUEST_METHOD'] ?? 'GET') === 'POST') {
            $password = $_POST['password'] ?? '';
            $confirm  = $_POST['password_confirm'] ?? '';
            $error = null;
            if (strlen($password) < 8) { $error = 'Mot de passe trop court (min 8).'; }
            if (!$error && $password !== $confirm) { $error = 'La confirmation ne correspond pas.'; }
            if ($error) {
                $this->view('auth/reset', ['uid' => $uid, 'token' => $token, 'error' => $error, '_layout' => 'auth']);
                return;
            }

            // Valider le token
            if (!$this->isValidToken($pdo, $uid, $token)) {
                $this->view('auth/reset', ['invalid' => true, '_layout' => 'auth']);
                return;
            }

            // Mettre à jour le mot de passe et marquer le token utilisé
            try {
                $pdo->beginTransaction();
                $up = $pdo->prepare('UPDATE users SET password = ? WHERE id = ?');
                $up->execute([password_hash($password, PASSWORD_DEFAULT), $uid]);
                $mark = $pdo->prepare('UPDATE password_resets SET used_at = NOW() WHERE user_id = ? AND token_hash = ? AND used_at IS NULL LIMIT 1');
                $mark->execute([$uid, hash('sha256', $token)]);
                // Optionnel: invalider tout autre token actif pour cet utilisateur
                $pdo->prepare('UPDATE password_resets SET used_at = COALESCE(used_at, NOW()) WHERE user_id = ? AND used_at IS NULL')->execute([$uid]);
                $pdo->commit();
            } catch (\Throwable $e) {
                $pdo->rollBack();
                $this->view('auth/reset', ['uid' => $uid, 'token' => $token, 'error' => 'Erreur lors de la mise à jour.', '_layout' => 'auth']);
                return;
            }

            $this->view('auth/reset', ['done' => true, '_layout' => 'auth']);
            return;
        }

        // GET: vérifier token pour afficher le formulaire
        if (!$uid || !$token || !$this->isValidToken($pdo, $uid, $token)) {
            $this->view('auth/reset', ['invalid' => true, '_layout' => 'auth']);
            return;
        }

        $this->view('auth/reset', ['uid' => $uid, 'token' => $token, '_layout' => 'auth']);
    }

    private function isValidToken(PDO $pdo, int $uid, string $token): bool
    {
        if ($uid <= 0 || $token === '') return false;
        $hash = hash('sha256', $token);
        $st = $pdo->prepare('SELECT COUNT(*) FROM password_resets WHERE user_id = ? AND token_hash = ? AND used_at IS NULL AND expires_at > NOW()');
        $st->execute([$uid, $hash]);
        return (int)$st->fetchColumn() > 0;
    }

    private function ensurePasswordResetsTable(PDO $pdo): void
    {
        $pdo->exec("CREATE TABLE IF NOT EXISTS password_resets (
            id INT AUTO_INCREMENT PRIMARY KEY,
            user_id INT NOT NULL,
            token_hash CHAR(64) NOT NULL,
            expires_at DATETIME NOT NULL,
            used_at DATETIME NULL,
            created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
            INDEX(user_id),
            INDEX(expires_at),
            UNIQUE KEY uniq_user_token (user_id, token_hash)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
    }
}
