conn = $db; } // --- 1. INSCRIPTION --- public function register($username, $email, $password) { // On vérifie si l'email ou le pseudo existe déjà if ($this->emailExists($email) || $this->usernameExists($username)) { return ["success" => false, "message" => "Pseudo ou email déjà utilisé."]; } // Génération d'un code de liaison unique (ex: WG-X89F2) $pairing_code = $this->generateUniquePairingCode(); // Hachage sécurisé du mot de passe $hashed_password = password_hash($password, PASSWORD_BCRYPT); $query = "INSERT INTO " . $this->table_name . " SET username = :username, email = :email, password = :password, pairing_code = :pairing_code"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":username", $username); $stmt->bindParam(":email", $email); $stmt->bindParam(":password", $hashed_password); $stmt->bindParam(":pairing_code", $pairing_code); if ($stmt->execute()) { return [ "success" => true, "message" => "Utilisateur créé avec succès.", "pairing_code" => $pairing_code ]; } return ["success" => false, "message" => "Erreur lors de l'inscription."]; } // --- 2. CONNEXION --- public function login($email, $password) { $query = "SELECT id, username, email, password, pairing_code, partner_id FROM " . $this->table_name . " WHERE email = :email LIMIT 0,1"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":email", $email); $stmt->execute(); if ($stmt->rowCount() > 0) { $row = $stmt->fetch(); // Vérification du mot de passe if (password_verify($password, $row['password'])) { return [ "success" => true, "user" => [ "id" => $row['id'], "username" => $row['username'], "email" => $row['email'], "pairing_code" => $row['pairing_code'], "partner_id" => $row['partner_id'] ] ]; } } return ["success" => false, "message" => "Identifiants incorrects."]; } // --- 3. LIAISON DE DEUX COMPTES --- public function linkPartner($current_user_id, $partner_code) { // 1. Trouver le partenaire qui possède ce code $query = "SELECT id, partner_id FROM " . $this->table_name . " WHERE pairing_code = :partner_code LIMIT 0,1"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":partner_code", $partner_code); $stmt->execute(); if ($stmt->rowCount() == 0) { return ["success" => false, "message" => "Code de liaison invalide."]; } $partner = $stmt->fetch(); $partner_id = $partner['id']; // Sécurité : On ne peut pas se lier à soi-même if ($partner_id == $current_user_id) { return ["success" => false, "message" => "Tu ne peux pas te lier à ton propre compte."]; } // Sécurité : Vérifier si le partenaire est déjà pris if (!is_null($partner['partner_id'])) { return ["success" => false, "message" => "Ce partenaire est déjà lié à quelqu'un d'autre."]; } try { // On commence une transaction SQL pour être sûr que les deux updates passent (ou aucun) $this->conn->beginTransaction(); // Update de l'utilisateur actuel $query1 = "UPDATE " . $this->table_name . " SET partner_id = :partner_id WHERE id = :current_id"; $stmt1 = $this->conn->prepare($query1); $stmt1->bindParam(":partner_id", $partner_id); $stmt1->bindParam(":current_id", $current_user_id); $stmt1->execute(); // Update du partenaire (réciprocité) $query2 = "UPDATE " . $this->table_name . " SET partner_id = :current_id WHERE id = :partner_id"; $stmt2 = $this->conn->prepare($query2); $stmt2->bindParam(":current_id", $current_user_id); $stmt2->bindParam(":partner_id", $partner_id); $stmt2->execute(); $stmt = $this->conn->prepare(" UPDATE movies m1 JOIN movies m2 ON m1.tmdb_id = m2.tmdb_id SET m1.is_common = 1, m2.is_common = 1 WHERE m1.user_id = ? AND m2.user_id = ? "); $stmt->execute([$current_user_id, $partner_id]); return ["success" => true]; $this->conn->commit(); return ["success" => true, "message" => "Comptes liés avec succès !"]; } catch (Exception $e) { $this->conn->rollBack(); return ["success" => false, "message" => "Erreur lors de la liaison."]; } } // --- 4. RÉCUPÉRER LE STATUT DE PAIRAGE --- public function getPairingStatus($user_id) { // On récupère les infos de l'utilisateur et de son partenaire s'il existe $query = "SELECT u1.pairing_code, u1.partner_id, u2.username AS partner_username FROM " . $this->table_name . " u1 LEFT JOIN " . $this->table_name . " u2 ON u1.partner_id = u2.id WHERE u1.id = :user_id LIMIT 1"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":user_id", $user_id); $stmt->execute(); if ($stmt->rowCount() > 0) { return ["success" => true, "data" => $stmt->fetch()]; } return ["success" => false, "message" => "Utilisateur introuvable."]; } // --- 5. CASSER LE LIEN (DÉLIAISON) --- public function unlinkPartner($userId) { // 1. On récupère l'ID du partenaire // (Pense bien à utiliser $this->conn ou $this->db selon ce que tu as corrigé tout à l'heure) $stmt = $this->db->prepare("SELECT partner_id FROM users WHERE id = ?"); $stmt->execute([$userId]); $partnerId = $stmt->fetchColumn(); if ($partnerId) { // 2. On récupère la liste exacte de tous les films en commun $stmt = $this->db->prepare(" SELECT tmdb_id, title, poster_path, media_type FROM movies WHERE is_common = 1 AND user_id IN (?, ?) GROUP BY tmdb_id, title, poster_path, media_type "); $stmt->execute([$userId, $partnerId]); $commonMovies = $stmt->fetchAll(PDO::FETCH_ASSOC); // 3. La distribution des biens : on s'assure que chacun a sa copie foreach ($commonMovies as $movie) { foreach ([$userId, $partnerId] as $uid) { // On vérifie si l'utilisateur possède déjà la ligne physique du film $checkStmt = $this->db->prepare("SELECT id FROM movies WHERE user_id = ? AND tmdb_id = ?"); $checkStmt->execute([$uid, $movie['tmdb_id']]); // S'il ne l'a pas, on lui insère sa copie perso if (!$checkStmt->fetch()) { $insertStmt = $this->db->prepare(" INSERT INTO movies (user_id, tmdb_id, title, poster_path, media_type, is_common) VALUES (?, ?, ?, ?, ?, 0) "); $insertStmt->execute([ $uid, $movie['tmdb_id'], $movie['title'], $movie['poster_path'], $movie['media_type'] ]); } } } // 4. On repasse TOUS les films de ces deux utilisateurs en perso $stmt = $this->db->prepare("UPDATE movies SET is_common = 0 WHERE user_id IN (?, ?)"); $stmt->execute([$userId, $partnerId]); // 5. On casse le lien dans la table users $stmt = $this->db->prepare("UPDATE users SET partner_id = NULL WHERE id IN (?, ?)"); $stmt->execute([$userId, $partnerId]); return ["success" => true, "message" => "Lien rompu et films sauvegardés dans les listes persos."]; } return ["success" => false, "message" => "Pas de partenaire trouvé."]; } // --- UTILS / VALIDATIONS --- private function emailExists($email) { $query = "SELECT id FROM " . $this->table_name . " WHERE email = :email LIMIT 1"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":email", $email); $stmt->execute(); return $stmt->rowCount() > 0; } private function usernameExists($username) { $query = "SELECT id FROM " . $this->table_name . " WHERE username = :username LIMIT 1"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":username", $username); $stmt->execute(); return $stmt->rowCount() > 0; } private function generateUniquePairingCode() { $characters = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; do { $code = 'WG-'; for ($i = 0; $i < 6; $i++) { $code .= $characters[rand(0, strlen($characters) - 1)]; } // On vérifie en BDD que le code n'existe pas déjà par pur hasard $query = "SELECT id FROM " . $this->table_name . " WHERE pairing_code = :code LIMIT 1"; $stmt = $this->conn->prepare($query); $stmt->bindParam(":code", $code); $stmt->execute(); $exists = $stmt->rowCount() > 0; } while ($exists); return $code; } public function getRealPartnerId($userId) { $stmt = $this->db->prepare("SELECT partner_id FROM users WHERE id = ?"); $stmt->execute([$userId]); return $stmt->fetchColumn() ?: null; } }