'int', 'rating' => 'float', 'watched' => 'bool', 'watch_count' => 'int', 'is_favorite' => 'bool', 'release_date' => 'date', 'last_watched_at' => 'datetime' ]; public function source() { return new Source($this->pdo); } public function markAsWatched(): bool { $this->watched = true; $this->watch_count += 1; $this->last_watched_at = date('Y-m-d H:i:s'); return $this->update($this->id, [ 'watched' => $this->watched, 'watch_count' => $this->watch_count, 'last_watched_at' => $this->last_watched_at ]); } public function markAsUnwatched(): bool { $this->watched = false; return $this->update($this->id, [ 'watched' => $this->watched ]); } public function toggleFavorite(): bool { return $this->update($this->id, [ 'is_favorite' => !$this->is_favorite ]); } public function updateRating(float $rating): bool { return $this->update($this->id, [ 'rating' => min(10.0, max(0.0, $rating)) ]); } public static function getStats(\PDO $pdo): array { $stmt = $pdo->query(" SELECT COUNT(*) as total_movies, COUNT(CASE WHEN watched = 1 THEN 1 END) as watched_movies, SUM(watch_count) as total_watches, AVG(rating) as avg_rating, COUNT(CASE WHEN is_favorite = 1 THEN 1 END) as favorite_movies, SUM(runtime_minutes) as total_runtime FROM movies "); return $stmt->fetch(PDO::FETCH_ASSOC); } public static function getRecent(\PDO $pdo, int $limit = 10): array { $stmt = $pdo->prepare(" SELECT m.*, s.display_name as source_name FROM movies m JOIN sources s ON m.source_id = s.id WHERE m.last_watched_at IS NOT NULL ORDER BY m.last_watched_at DESC LIMIT :limit "); $stmt->execute(['limit' => $limit]); return $stmt->fetchAll(PDO::FETCH_ASSOC); } public static function getTotalCount(\PDO $pdo, string $search = ''): int { $sql = "SELECT COUNT(*) as count FROM movies m JOIN sources s ON m.source_id = s.id"; $params = []; if (!empty($search)) { $sql .= " WHERE m.title LIKE :search"; $params['search'] = "%{$search}%"; } $stmt = $pdo->prepare($sql); $stmt->execute($params); return (int) $stmt->fetch()['count']; } public static function getAllWithPagination(\PDO $pdo, int $page, int $perPage, string $search = ''): array { $offset = ($page - 1) * $perPage; $sql = " SELECT m.*, s.display_name as source_name FROM movies m JOIN sources s ON m.source_id = s.id "; $params = []; if (!empty($search)) { $sql .= " WHERE m.title LIKE :search"; $params['search'] = "%{$search}%"; } $sql .= " ORDER BY m.title ASC LIMIT :limit OFFSET :offset"; $stmt = $pdo->prepare($sql); $stmt->bindValue(':limit', $perPage, \PDO::PARAM_INT); $stmt->bindValue(':offset', $offset, \PDO::PARAM_INT); foreach ($params as $key => $value) { $stmt->bindValue(":{$key}", $value); } $stmt->execute(); return $stmt->fetchAll(\PDO::FETCH_ASSOC); } public static function getAll(\PDO $pdo, int $limit = 100): array { $stmt = $pdo->prepare(" SELECT m.*, s.display_name as source_name FROM movies m JOIN sources s ON m.source_id = s.id ORDER BY m.title ASC LIMIT :limit "); $stmt->execute(['limit' => $limit]); return $stmt->fetchAll(\PDO::FETCH_ASSOC); } }