import sys
import os
import sqlite3
import requests
import webbrowser
import feedparser
import re
from pathlib import Path
from dataclasses import dataclass, field
from typing import List, Optional, Tuple, Dict, Set
from urllib.parse import urlencode, urlparse
from datetime import datetime, timedelta
from functools import lru_cache
from tenacity import retry, stop_after_attempt, wait_exponential
from PyQt5.QtWidgets import (
    QApplication, QMainWindow, QVBoxLayout, QWidget, QLineEdit, QPushButton,
    QLabel, QScrollArea, QListWidget, QInputDialog, QMessageBox,
    QHBoxLayout, QFrame, QMenu, QToolBar, QStatusBar, QGridLayout, QComboBox,
    QListWidgetItem, QCheckBox, QSizePolicy, QProgressBar,
    QAction, QFileDialog, QStackedWidget, QProgressDialog
)
from PyQt5.QtGui import QPixmap, QIcon, QFont, QPalette, QColor
from PyQt5.QtCore import Qt, QObject, QRunnable, QThreadPool, pyqtSignal, QTimer, QSize
import logging
from logging.handlers import RotatingFileHandler
import yt_dlp

# --- CONFIGURAZIONE LOGGING ---
log_dir = Path.home() / ".purpletube_player" if os.name != 'nt' else Path(os.getenv('APPDATA')) / "PurpleTube"
log_path = log_dir / "app.log"
try:
    log_dir.mkdir(parents=True, exist_ok=True)
    if os.name != 'nt':
        log_dir.chmod(0o755)
except Exception as e:
    print(f"[WARNING] Impossibile creare {log_dir}. Errore: {e}")
    log_dir = Path(__file__).parent / "purpletube_logs"
    log_dir.mkdir(parents=True, exist_ok=True)
    log_path = log_dir / "app.log"
logging.basicConfig(
    level=logging.DEBUG,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        RotatingFileHandler(log_path, maxBytes=1024 * 1024, backupCount=3, encoding='utf-8', delay=True),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger(__name__)

# --- DATA MODELS ---
@dataclass
class Video:
    title: str
    url: str
    thumbnail_url: str
    duration: str
    video_id: str
    platform: str = "PeerTube"
    author: str = "Sconosciuto"
    published: Optional[datetime] = None

    def to_dict(self):
        return {
            'title': self.title,
            'url': self.url,
            'thumbnail_url': self.thumbnail_url,
            'duration': self.duration,
            'video_id': self.video_id,
            'platform': self.platform,
            'author': self.author,
            'published': self.published.isoformat() if self.published else None
        }

@dataclass
class Playlist:
    name: str
    videos: List[Video] = field(default_factory=list)
    id: Optional[int] = None

    def add_video(self, video: Video):
        if video.video_id not in [v.video_id for v in self.videos]:
            self.videos.append(video)
            return True
        return False

    def remove_video(self, video_id: str) -> bool:
        for i, video in enumerate(self.videos):
            if video.video_id == video_id:
                self.videos.pop(i)
                return True
        return False

@dataclass
class RSSFeed:
    url: str
    title: str
    id: Optional[int] = None
    last_updated: Optional[datetime] = None
    is_channel: bool = False

@dataclass
class FeedItem:
    title: str
    url: str
    thumbnail_url: str
    duration: str
    video_id: str
    published: datetime
    author: str
    platform: str = "PeerTube"

# --- DATABASE MANAGER ---
class DBManager:
    def __init__(self):
        if os.name == 'nt':
            self.DB_DIR = Path(os.getenv('APPDATA')) / "purpleTube"
        else:
            self.DB_DIR = Path.home() / ".purpletube_player"
        self.DB_PATH = self.DB_DIR / "database.db"
        try:
            self.DB_DIR.mkdir(parents=True, exist_ok=True)
            if os.name != 'nt':
                self.DB_DIR.chmod(0o755)
            test_file = self.DB_DIR / ".write_test"
            test_file.touch()
            test_file.unlink()
        except Exception as e:
            logger.error(f"Impossibile configurare {self.DB_DIR}: {e}")
            self.DB_DIR = Path(__file__).parent / "purpletube_data"
            self.DB_DIR.mkdir(parents=True, exist_ok=True)
            if os.name != 'nt':
                self.DB_DIR.chmod(0o755)
        self.DB_PATH = self.DB_DIR / "database.db"
        self._init_db()
        self._create_indices()
        self._verify_db_integrity()
        self._verify_setup()

    def _verify_setup(self):
        errors = []
        if not self.DB_DIR.exists():
            errors.append(f"Cartella {self.DB_DIR} non esiste.")
        else:
            if not os.access(self.DB_DIR, os.W_OK):
                errors.append(f"Permessi insufficienti per scrivere in {self.DB_DIR}")
        if not log_path.exists():
            try:
                with open(log_path, 'a'):
                    pass
            except Exception as e:
                errors.append(f"Impossibile creare {log_path}: {e}")
        if errors:
            logger.error("Problemi di configurazione:")
            for error in errors:
                logger.error(f"  - {error}")
            logger.error("Tentativo con percorso alternativo...")
            self.DB_DIR = Path(__file__).parent / "purpletube_data"
            self.DB_PATH = self.DB_DIR / "database.db"
            self.DB_DIR.mkdir(parents=True, exist_ok=True)
            if os.name != 'nt':
                self.DB_DIR.chmod(0o755)
            logger.error(f"Nuovo percorso database: {self.DB_DIR}")

    def _init_db(self):
        try:
            with sqlite3.connect(self.DB_PATH) as conn:
                conn.execute("PRAGMA foreign_keys = ON")
                conn.execute("PRAGMA journal_mode = WAL")
                conn.execute("PRAGMA synchronous = NORMAL")
                conn.execute("""
                CREATE TABLE IF NOT EXISTS playlists (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    name TEXT UNIQUE NOT NULL,
                    created_at TEXT DEFAULT CURRENT_TIMESTAMP,
                    updated_at TEXT DEFAULT CURRENT_TIMESTAMP
                );
                """)
                conn.execute("""
                CREATE TABLE IF NOT EXISTS playlist_videos (
                    playlist_id INTEGER NOT NULL,
                    video_id TEXT NOT NULL,
                    position INTEGER DEFAULT 0,
                    title TEXT NOT NULL,
                    url TEXT NOT NULL,
                    thumbnail_url TEXT,
                    duration TEXT DEFAULT '0',
                    platform TEXT DEFAULT 'PeerTube',
                    author TEXT DEFAULT 'Sconosciuto',
                    published TEXT,
                    added_at TEXT DEFAULT CURRENT_TIMESTAMP,
                    PRIMARY KEY (playlist_id, video_id),
                    FOREIGN KEY (playlist_id) REFERENCES playlists(id) ON DELETE CASCADE
                );
                """)
                conn.execute("""
                CREATE TABLE IF NOT EXISTS rss_feeds (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    url TEXT UNIQUE NOT NULL,
                    title TEXT NOT NULL,
                    last_updated TEXT,
                    is_channel INTEGER DEFAULT 0,
                    created_at TEXT DEFAULT CURRENT_TIMESTAMP
                );
                """)
                conn.execute("""
                CREATE TABLE IF NOT EXISTS feed_items (
                    feed_id INTEGER NOT NULL,
                    video_id TEXT NOT NULL,
                    title TEXT NOT NULL,
                    url TEXT NOT NULL,
                    thumbnail_url TEXT,
                    duration TEXT DEFAULT '0',
                    published TEXT NOT NULL,
                    author TEXT DEFAULT 'Sconosciuto',
                    platform TEXT DEFAULT 'PeerTube',
                    added_at TEXT DEFAULT CURRENT_TIMESTAMP,
                    PRIMARY KEY (feed_id, video_id),
                    FOREIGN KEY (feed_id) REFERENCES rss_feeds(id) ON DELETE CASCADE
                );
                """)
                conn.execute("""
                CREATE TABLE IF NOT EXISTS user_preferences (
                    id INTEGER PRIMARY KEY AUTOINCREMENT,
                    key TEXT UNIQUE NOT NULL,
                    value TEXT,
                    updated_at TEXT DEFAULT CURRENT_TIMESTAMP
                );
                """)
                conn.execute("INSERT OR IGNORE INTO playlists (name) VALUES ('Watch Later')")
                conn.commit()
                logger.info(f"Database inizializzato in: {self.DB_PATH}")
        except sqlite3.Error as e:
            logger.error(f"Errore durante l'inizializzazione del database: {e}")
            raise

    def _create_indices(self):
        with sqlite3.connect(self.DB_PATH) as conn:
            conn.execute("CREATE INDEX IF NOT EXISTS idx_playlist_videos_playlist ON playlist_videos(playlist_id)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_playlist_videos_position ON playlist_videos(playlist_id, position)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_playlist_videos_video ON playlist_videos(video_id)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_playlist_videos_added ON playlist_videos(added_at)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_feed_items_feed ON feed_items(feed_id)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_feed_items_published ON feed_items(published)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_feed_items_video ON feed_items(video_id)")
            conn.execute("CREATE INDEX IF NOT EXISTS idx_feed_items_added ON feed_items(added_at)")
            conn.commit()

    def _verify_db_integrity(self):
        with sqlite3.connect(self.DB_PATH) as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT 1 FROM playlists WHERE name = 'Watch Later'")
            if not cursor.fetchone():
                cursor.execute("INSERT INTO playlists (name) VALUES ('Watch Later')")
            cursor.execute("""
            DELETE FROM playlist_videos
            WHERE playlist_id NOT IN (SELECT id FROM playlists)
            """)
            cursor.execute("""
            DELETE FROM feed_items
            WHERE feed_id NOT IN (SELECT id FROM rss_feeds)
            """)
            conn.commit()

    def get_connection(self):
        conn = sqlite3.connect(self.DB_PATH)
        conn.execute("PRAGMA foreign_keys = ON")
        return conn

    def clear_all_user_data(self) -> bool:
        try:
            with sqlite3.connect(self.DB_PATH) as conn:
                cursor = conn.cursor()
                cursor.execute("SELECT id FROM playlists WHERE name = 'Watch Later'")
                wl_id = cursor.fetchone()
                cursor.execute("DELETE FROM playlist_videos")
                cursor.execute("DELETE FROM playlists WHERE name != 'Watch Later'")
                cursor.execute("DELETE FROM feed_items")
                cursor.execute("DELETE FROM rss_feeds")
                cursor.execute("DELETE FROM user_preferences")
                if not wl_id:
                    cursor.execute("INSERT OR IGNORE INTO playlists (name) VALUES ('Watch Later')")
                conn.commit()
            return True
        except Exception as e:
            logger.error(f"Errore cancellazione dati utente: {e}")
            return False

    def close(self):
        pass

db_manager = DBManager()

# --- SERVIZI ---
class PlaylistService:
    @staticmethod
    @lru_cache(maxsize=1)
    def get_watch_later_playlist() -> Optional[Playlist]:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT id FROM playlists WHERE name = 'Watch Later'")
            row = cursor.fetchone()
            if row:
                pid = row[0]
                cursor.execute("""
                    SELECT video_id, title, url, thumbnail_url, duration, platform, author, published
                    FROM playlist_videos
                    WHERE playlist_id = ?
                    ORDER BY position ASC
                """, (pid,))
                videos = []
                for vid, t, u, thumb, d, plat, auth, pub in cursor.fetchall():
                    try:
                        video = Video(
                            title=t or "Senza titolo",
                            url=u or "",
                            thumbnail_url=thumb or "",
                            duration=d or "0",
                            video_id=vid,
                            platform=plat or "PeerTube",
                            author=auth or "Sconosciuto",
                            published=datetime.fromisoformat(pub) if pub else None
                        )
                        videos.append(video)
                    except Exception as e:
                        logger.error(f"Errore nel parsing del video {vid}: {e}")
                return Playlist(name="Watch Later", videos=videos, id=pid)
        return None

    @staticmethod
    def get_playlists() -> List[Playlist]:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT id, name FROM playlists")
            playlists = []
            for pid, name in cursor.fetchall():
                cursor.execute("""
                    SELECT video_id, title, url, thumbnail_url, duration, platform, author, published
                    FROM playlist_videos
                    WHERE playlist_id = ?
                    ORDER BY position ASC
                """, (pid,))
                videos = []
                for vid, t, u, thumb, d, plat, auth, pub in cursor.fetchall():
                    try:
                        video = Video(
                            title=t or "Senza titolo",
                            url=u or "",
                            thumbnail_url=thumb or "",
                            duration=d or "0",
                            video_id=vid,
                            platform=plat or "PeerTube",
                            author=auth or "Sconosciuto",
                            published=datetime.fromisoformat(pub) if pub else None
                        )
                        videos.append(video)
                    except Exception as e:
                        logger.error(f"Errore nel parsing del video {vid}: {e}")
                playlists.append(Playlist(name=name, videos=videos, id=pid))
            return playlists

    @staticmethod
    def get_playlist_videos(playlist_id: int) -> List[Video]:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT video_id, title, url, thumbnail_url, duration, platform, author, published
                FROM playlist_videos
                WHERE playlist_id = ?
                ORDER BY position ASC
            """, (playlist_id,))
            videos = []
            for vid, t, u, thumb, d, plat, auth, pub in cursor.fetchall():
                try:
                    video = Video(
                        title=t or "Senza titolo",
                        url=u or "",
                        thumbnail_url=thumb or "",
                        duration=d or "0",
                        video_id=vid,
                        platform=plat or "PeerTube",
                        author=auth or "Sconosciuto",
                        published=datetime.fromisoformat(pub) if pub else None
                    )
                    videos.append(video)
                except Exception as e:
                    logger.error(f"Errore nel parsing del video {vid}: {e}")
            return videos

    @staticmethod
    def save_playlist(playlist: Playlist) -> int:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("INSERT INTO playlists (name) VALUES (?)", (playlist.name,))
            playlist.id = cursor.lastrowid
            conn.commit()
        return playlist.id

    @staticmethod
    def add_to_playlist(playlist_id: int, video: Video) -> bool:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute(
                "SELECT COUNT(*) FROM playlist_videos WHERE playlist_id=? AND video_id=?",
                (playlist_id, video.video_id)
            )
            if cursor.fetchone()[0] > 0:
                return False
            cursor.execute(
                "SELECT COALESCE(MAX(position),0) FROM playlist_videos WHERE playlist_id=?",
                (playlist_id,)
            )
            max_pos = cursor.fetchone()[0] or 0
            cursor.execute("""
                INSERT INTO playlist_videos
                (playlist_id, video_id, position, title, url, thumbnail_url, duration, platform, author, published)
                VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
            """, (
                playlist_id, video.video_id, max_pos+1, video.title, video.url,
                video.thumbnail_url, video.duration, video.platform, video.author,
                video.published.isoformat() if video.published else None
            ))
            cursor.execute("""
                UPDATE playlists
                SET updated_at = CURRENT_TIMESTAMP
                WHERE id = ?
            """, (playlist_id,))
            conn.commit()
        return True

    @staticmethod
    def remove_from_playlist(playlist_id: int, video_id: str) -> bool:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute(
                "SELECT position FROM playlist_videos WHERE playlist_id=? AND video_id=?",
                (playlist_id, video_id)
            )
            pos_row = cursor.fetchone()
            if not pos_row:
                return False
            pos = pos_row[0]
            cursor.execute(
                "DELETE FROM playlist_videos WHERE playlist_id=? AND video_id=?",
                (playlist_id, video_id)
            )
            cursor.execute("""
                UPDATE playlist_videos
                SET position = position - 1
                WHERE playlist_id = ? AND position > ?
            """, (playlist_id, pos))
            cursor.execute("""
                UPDATE playlists
                SET updated_at = CURRENT_TIMESTAMP
                WHERE id = ?
            """, (playlist_id,))
            conn.commit()
        return True

    @staticmethod
    def remove_playlist(playlist_name: str) -> bool:
        if playlist_name == "Watch Later":
            return False
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT id FROM playlists WHERE name=?", (playlist_name,))
            row = cursor.fetchone()
            if not row:
                return False
            pid = row[0]
            cursor.execute("DELETE FROM playlists WHERE id=?", (pid,))
            conn.commit()
        return True

    @staticmethod
    def update_playlist_name(playlist_id: int, new_name: str) -> bool:
        if new_name == "Watch Later":
            return False
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT 1 FROM playlists WHERE name = ? AND id != ?", (new_name, playlist_id))
            if cursor.fetchone():
                return False
            cursor.execute("""
                UPDATE playlists
                SET name = ?, updated_at = CURRENT_TIMESTAMP
                WHERE id = ?
            """, (new_name, playlist_id))
            conn.commit()
        return True

    @staticmethod
    def reorder_playlist_videos(playlist_id: int, video_ids: List[str]) -> bool:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("""
                SELECT COUNT(*)
                FROM playlist_videos
                WHERE playlist_id = ? AND video_id IN ({})
            """.format(','.join(['?']*len(video_ids))), [playlist_id] + video_ids)
            if cursor.fetchone()[0] != len(video_ids):
                return False
            for position, video_id in enumerate(video_ids):
                cursor.execute("""
                    UPDATE playlist_videos
                    SET position = ?
                    WHERE playlist_id = ? AND video_id = ?
                """, (position, playlist_id, video_id))
            cursor.execute("""
                UPDATE playlists
                SET updated_at = CURRENT_TIMESTAMP
                WHERE id = ?
            """, (playlist_id,))
            conn.commit()
        return True

class SearchService:
    SESSION = requests.Session()
    SESSION.headers.update({"User-Agent": "purpleTubePlayer/1.0"})

    @staticmethod
    @retry(stop=stop_after_attempt(3), wait=wait_exponential(multiplier=1, min=2, max=10))
    def search_videos(
        query: str,
        page: int = 1,
        count: int = 50,
        sort_by: str = "recent",
        published_after: str = None
    ) -> Tuple[List[Video], int]:
        try:
            params = {
                'search': query,
                'start': (page-1)*count,
                'count': count,
                'nsfw': 'false'
            }
            if published_after:
                params['publishedAfter'] = published_after
            if sort_by == "recent":
                params['sort'] = '-publishedAt'
            elif sort_by == "views":
                params['sort'] = '-views'
            elif sort_by == "duration":
                params['sort'] = 'duration'
            else:
                params['sort'] = '-match'
            url = f"https://sepiasearch.org/api/v1/search/videos?{urlencode(params)}"
            resp = SearchService.SESSION.get(url, timeout=10)
            resp.raise_for_status()
            data = resp.json()
            videos = []
            for item in data.get("data", []):
                try:
                    video = Video(
                        title=item.get("name", "No title"),
                        url=item.get("url", ""),
                        thumbnail_url=item.get("thumbnailUrl", ""),
                        duration=str(item.get("duration", 0)),
                        video_id=str(item.get("uuid", "")),
                        author=item.get("account", {}).get("name", "Sconosciuto"),
                        published=datetime.fromisoformat(item.get("publishedAt").replace('Z', '+00:00')) if item.get("publishedAt") else None
                    )
                    videos.append(video)
                except Exception as e:
                    logger.error(f"Errore nel parsing del video {item.get('uuid')}: {e}")
            return videos, data.get("total", 0)
        except Exception as e:
            logger.error(f"Errore ricerca SepiaSearch: {e}")
            return [], 0

class RSSService:
    SESSION = requests.Session()
    SESSION.headers.update({"User-Agent": "purpleTubePlayer/1.0"})

    @staticmethod
    def parse_peertube_feed(feed_url: str) -> Tuple[RSSFeed, List[FeedItem]]:
        try:
            feed = feedparser.parse(feed_url)
            if not feed.entries:
                raise ValueError("Feed vuoto o non valido")
            is_channel = "account" in feed.feed.get("link", "").lower() if feed.feed else False
            rss_feed = RSSFeed(
                url=feed_url,
                title=feed.feed.get("title", "Feed senza titolo"),
                last_updated=datetime.now(),
                is_channel=is_channel
            )
            items = []
            for entry in feed.entries:
                duration = "0"
                for tag in entry.get("media_content", []):
                    if isinstance(tag, dict) and tag.get("medium") == "video":
                        duration = str(tag.get("duration", "0"))
                        break
                thumbnail_url = ""
                if hasattr(entry, "media_thumbnail"):
                    thumbnail_url = entry.media_thumbnail[0]["url"] if entry.media_thumbnail else ""
                elif hasattr(entry, "enclosures") and entry.enclosures:
                    thumbnail_url = entry.enclosures[0].get("url", "")
                video_url = entry.link
                video_id = ""
                if video_url:
                    parsed = urlparse(video_url)
                    if parsed.path:
                        video_id = parsed.path.split("/")[-1]
                published = datetime.now()
                if hasattr(entry, "published_parsed"):
                    published = datetime(*entry.published_parsed[:6])
                items.append(FeedItem(
                    title=entry.get("title", "No title"),
                    url=video_url,
                    thumbnail_url=thumbnail_url,
                    duration=duration,
                    video_id=video_id,
                    published=published,
                    author=entry.get("author", "Sconosciuto"),
                    platform="PeerTube"
                ))
            return rss_feed, items
        except Exception as e:
            logger.error(f"Errore parsing feed RSS: {e}")
            raise

    @staticmethod
    def add_feed(feed_url: str) -> bool:
        try:
            feed, items = RSSService.parse_peertube_feed(feed_url)
            with db_manager.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute("""
                    INSERT INTO rss_feeds (url, title, last_updated, is_channel)
                    VALUES (?, ?, ?, ?)
                """, (feed.url, feed.title, feed.last_updated.isoformat(), int(feed.is_channel)))
                feed_id = cursor.lastrowid
                for item in items:
                    cursor.execute("""
                        INSERT OR IGNORE INTO feed_items
                        (feed_id, video_id, title, url, thumbnail_url, duration, published, author, platform)
                        VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
                    """, (
                        feed_id, item.video_id, item.title, item.url, item.thumbnail_url,
                        item.duration, item.published.isoformat(), item.author, item.platform
                    ))
                conn.commit()
            return True
        except Exception as e:
            logger.error(f"Errore aggiunta feed: {e}")
            return False

    @staticmethod
    def get_feeds() -> List[RSSFeed]:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute("SELECT id, url, title, last_updated, is_channel FROM rss_feeds")
            return [
                RSSFeed(
                    id=row[0],
                    url=row[1],
                    title=row[2],
                    last_updated=datetime.fromisoformat(row[3]) if row[3] else None,
                    is_channel=bool(row[4])
                )
                for row in cursor.fetchall()
            ]

    @staticmethod
    def get_feed_items(feed_id: int, limit: int = None) -> List[FeedItem]:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            query = """
                SELECT video_id, title, url, thumbnail_url, duration, published, author, platform
                FROM feed_items
                WHERE feed_id = ?
                ORDER BY published DESC
            """
            if limit is not None:
                query += " LIMIT ?"
                cursor.execute(query, (feed_id, limit))
            else:
                cursor.execute(query, (feed_id,))
            return [
                FeedItem(
                    video_id=row[0],
                    title=row[1],
                    url=row[2],
                    thumbnail_url=row[3],
                    duration=row[4],
                    published=datetime.fromisoformat(row[5]),
                    author=row[6],
                    platform=row[7]
                )
                for row in cursor.fetchall()
            ]

    @staticmethod
    def remove_feed(feed_id: int) -> bool:
        try:
            with db_manager.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute("DELETE FROM rss_feeds WHERE id = ?", (feed_id,))
                conn.commit()
            return True
        except Exception as e:
            logger.error(f"Errore rimozione feed: {e}")
            return False

    @staticmethod
    def refresh_feed(feed_id: int) -> bool:
        try:
            with db_manager.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute("SELECT url FROM rss_feeds WHERE id = ?", (feed_id,))
                row = cursor.fetchone()
                if not row:
                    return False
                feed_url = row[0]
                feed, items = RSSService.parse_peertube_feed(feed_url)
                cursor.execute("""
                    UPDATE rss_feeds
                    SET title = ?, last_updated = ?
                    WHERE id = ?
                """, (feed.title, datetime.now().isoformat(), feed_id))
                existing_ids = {row[0] for row in cursor.execute(
                    "SELECT video_id FROM feed_items WHERE feed_id = ?", (feed_id,)
                ).fetchall()}
                for item in items:
                    if item.video_id not in existing_ids:
                        cursor.execute("""
                            INSERT INTO feed_items
                            (feed_id, video_id, title, url, thumbnail_url, duration, published, author, platform)
                            VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
                        """, (
                            feed_id, item.video_id, item.title, item.url, item.thumbnail_url,
                            item.duration, item.published.isoformat(), item.author, item.platform
                        ))
                conn.commit()
            return True
        except Exception as e:
            logger.error(f"Errore aggiornamento feed: {e}")
            return False

    @staticmethod
    def get_all_feed_items(limit: int = None) -> List[FeedItem]:
        with db_manager.get_connection() as conn:
            cursor = conn.cursor()
            query = """
                SELECT fi.video_id, fi.title, fi.url, fi.thumbnail_url, fi.duration,
                       fi.published, fi.author, fi.platform, f.title as feed_title
                FROM feed_items fi
                JOIN rss_feeds f ON fi.feed_id = f.id
                ORDER BY fi.published DESC
            """
            if limit is not None:
                query += " LIMIT ?"
                cursor.execute(query, (limit,))
            else:
                cursor.execute(query)
            return [
                FeedItem(
                    video_id=row[0],
                    title=row[1],
                    url=row[2],
                    thumbnail_url=row[3],
                    duration=row[4],
                    published=datetime.fromisoformat(row[5]),
                    author=row[6],
                    platform=row[7]
                )
                for row in cursor.fetchall()
            ]

    @staticmethod
    def clear_all_feeds() -> bool:
        try:
            with db_manager.get_connection() as conn:
                cursor = conn.cursor()
                cursor.execute("DELETE FROM feed_items")
                cursor.execute("DELETE FROM rss_feeds")
                conn.commit()
            return True
        except Exception as e:
            logger.error(f"Errore cancellazione feed: {e}")
            return False

# --- THUMBNAIL LOADER ---
class ThumbnailLoader(QRunnable):
    def __init__(self, url: str, label: QLabel):
        super().__init__()
        self.url = url
        self.label = label
        self._running = True

    def run(self):
        if not self._running:
            return
        try:
            response = SearchService.SESSION.get(self.url, timeout=5)
            response.raise_for_status()
            pixmap = QPixmap()
            pixmap.loadFromData(response.content)
            if self._running and not pixmap.isNull():
                scaled = pixmap.scaled(
                    self.label.size(),
                    Qt.KeepAspectRatio,
                    Qt.SmoothTransformation
                )
                self.label.setPixmap(scaled)
        except requests.RequestException as e:
            logger.warning(f"Errore caricamento thumbnail: {e}")

    def stop(self):
        self._running = False

# --- DOWNLOAD WORKER ---
class WorkerSignals(QObject):
    progress = pyqtSignal(int)
    finished = pyqtSignal(str, str)
    error = pyqtSignal(str, str)

class DownloadWorker(QRunnable):
    def __init__(self, video_url: str, output_path: str):
        super().__init__()
        self.signals = WorkerSignals()
        self.video_url = video_url
        self.output_path = output_path
        self._running = True

    def run(self):
        if not self._running:
            return
        ydl_opts = {
            'format': 'bestvideo+bestaudio/best',
            'outtmpl': str(Path(self.output_path) / '%(title)s.%(ext)s'),
            'progress_hooks': [self._progress_hook],
            'quiet': True,
            'no_warnings': True,
            'no_color': True
        }
        try:
            with yt_dlp.YoutubeDL(ydl_opts) as ydl:
                info_dict = ydl.extract_info(self.video_url, download=True)
                filename = ydl.prepare_filename(info_dict)
                self.signals.finished.emit(filename, info_dict.get('title', 'Video'))
        except Exception as e:
            self.signals.error.emit(self.video_url, str(e))

    def _progress_hook(self, d):
        if d['status'] == 'downloading':
            percent_str = d.get('_percent_str', '0')
            clean_percent_str = re.sub(r'\x1b\[[0-9;]*m', '', percent_str)
            progress = int(float(clean_percent_str.replace('%', '').strip()))
            self.signals.progress.emit(progress)

    def stop(self):
        self._running = False

# --- THEME ---
class Theme:
    PRIMARY = "#6a5acd"
    PRIMARY_HOVER = "#7a6bdb"
    PRIMARY_PRESSED = "#5a4bc9"
    SECONDARY = "#AAAAAA"
    SECONDARY_HOVER = "#CCCCCC"
    TERTIARY = "#FF9800"
    TERTIARY_HOVER = "#E68A00"
    BACKGROUND = "#0F0F0F"
    BACKGROUND_LIGHT = "#181818"
    SURFACE = "#212121"
    SURFACE_HOVER = "#2A2A2A"
    SURFACE_PRESSED = "#323232"
    TEXT_PRIMARY = "#FFFFFF"
    TEXT_SECONDARY = "#AAAAAA"
    TEXT_DISABLED = "#6B6B6B"
    TEXT_LINK = "#6a5acd"
    BORDER = "#3A3A3A"
    BORDER_ACTIVE = "#6a5acd"
    BORDER_HOVER = "#6B6B6B"
    SUCCESS = "#00FF66"
    DANGER = "#FF3333"
    WARNING = "#FFCC00"
    INFO = "#FF9800"

    @classmethod
    def global_stylesheet(cls) -> str:
        return f"""
        QMainWindow, QDialog {{
            background: {cls.BACKGROUND};
            font-family: 'Inter', 'Segoe UI', 'Roboto', sans-serif;
            font-size: 14px;
            color: {cls.TEXT_PRIMARY};
        }}
        QFrame[role="card"], QGroupBox {{
            background: {cls.SURFACE};
            border-radius: 8px;
            border: 1px solid {cls.BORDER};
            padding: 12px;
            margin: 6px;
        }}
        QToolBar {{
            background: {cls.BACKGROUND_LIGHT};
            border: none;
            padding: 8px;
            spacing: 6px;
            border-radius: 8px;
            margin: 6px;
        }}
        QToolBar QToolButton {{
            background: transparent;
            border: none;
            padding: 6px;
            border-radius: 6px;
            icon-size: 18px;
        }}
        QToolBar QToolButton:hover {{
            background: rgba(106, 90, 205, 0.1);
        }}
        QToolBar QToolButton:checked {{
            background: rgba(106, 90, 205, 0.2);
        }}
        QStatusBar {{
            background: {cls.SURFACE};
            color: {cls.TEXT_SECONDARY};
            padding: 6px 12px;
            border-top: 1px solid {cls.BORDER};
            font-size: 14px;
        }}
        QLineEdit, QTextEdit, QPlainTextEdit, QComboBox {{
            background: {cls.SURFACE};
            border: 1px solid {cls.BORDER};
            border-radius: 6px;
            color: {cls.TEXT_PRIMARY};
            padding: 8px 12px;
            selection-background-color: {cls.PRIMARY};
        }}
        QLineEdit:focus, QTextEdit:focus, QPlainTextEdit:focus, QComboBox:focus {{
            border: 1px solid {cls.PRIMARY};
        }}
        QLineEdit[role="search"] {{
            border-radius: 16px;
            padding-left: 32px;
        }}
        QPushButton {{
            background: {cls.PRIMARY};
            color: white;
            border: none;
            border-radius: 6px;
            padding: 8px 16px;
            font-family: 'Inter Medium', 'Segoe UI Semibold', sans-serif;
            font-weight: 500;
        }}
        QPushButton:hover {{
            background: {cls.PRIMARY_HOVER};
        }}
        QPushButton:pressed {{
            background: {cls.PRIMARY_PRESSED};
        }}
        QPushButton:disabled {{
            background: {cls.BORDER};
            color: {cls.TEXT_DISABLED};
        }}
        QPushButton[role="secondary"] {{
            background: {cls.SECONDARY};
        }}
        QPushButton[role="secondary"]:hover {{
            background: {cls.SECONDARY_HOVER};
        }}
        QPushButton[role="tertiary"] {{
            background: {cls.TERTIARY};
        }}
        QPushButton[role="danger"] {{
            background: {cls.DANGER};
        }}
        QPushButton[role="danger"]:hover {{
            background: #d32f2f;
        }}
        QScrollBar:vertical {{
            border: none;
            background: {cls.BACKGROUND_LIGHT};
            width: 8px;
            margin: 0px;
            border-radius: 4px;
        }}
        QScrollBar::handle:vertical {{
            background: {cls.PRIMARY};
            min-height: 16px;
            border-radius: 4px;
        }}
        QScrollBar::handle:vertical:hover {{
            background: {cls.PRIMARY_HOVER};
        }}
        QScrollBar::add-line, QScrollBar::sub-line {{
            background: none;
            border: none;
        }}
        QCheckBox::indicator, QRadioButton::indicator {{
            width: 16px;
            height: 16px;
        }}
        QCheckBox::indicator:checked {{
            background: {cls.PRIMARY};
            border-radius: 4px;
            border: none;
        }}
        QRadioButton::indicator:checked {{
            background: {cls.PRIMARY};
            border-radius: 8px;
            border: none;
        }}
        QProgressBar {{
            border: none;
            border-radius: 4px;
            text-align: center;
            background: {cls.SURFACE};
        }}
        QProgressBar::chunk {{
            background: {cls.PRIMARY};
            border-radius: 4px;
        }}
        QMenu {{
            background: {cls.SURFACE};
            border: 1px solid {cls.BORDER};
            border-radius: 6px;
            padding: 4px;
            color: {cls.TEXT_PRIMARY};
        }}
        QMenu::item:selected {{
            background: rgba(106, 90, 205, 0.2);
            border-radius: 4px;
        }}
        QListWidget {{
            background: {cls.SURFACE};
            border: 1px solid {cls.BORDER};
            border-radius: 6px;
            color: {cls.TEXT_PRIMARY};
            font-family: 'Inter';
            font-size: 14px;
            padding: 6px;
        }}
        QListWidget::item {{
            padding: 8px;
            border-radius: 4px;
        }}
        QListWidget::item:selected {{
            background: {cls.PRIMARY};
            color: white;
        }}
        QListWidget::item:hover {{
            background: {cls.SURFACE_HOVER};
        }}
        """

    @classmethod
    def search_bar_style(cls) -> str:
        return f"""
        QLineEdit[role="search"] {{
            background: {cls.SURFACE};
            border: 1px solid {cls.BORDER};
            border-radius: 16px;
            color: {cls.TEXT_PRIMARY};
            padding: 0 32px 0 16px;
            min-height: 32px;
        }}
        QLineEdit[role="search"]:focus {{
            border: 1px solid {cls.PRIMARY};
        }}
        """

    @classmethod
    def video_card_style(cls) -> str:
        return f"""
        VideoCard {{
            background: {cls.SURFACE};
            border-radius: 8px;
            border: 1px solid {cls.BORDER};
            color: {cls.TEXT_PRIMARY};
        }}
        #title_label {{
            font-weight: 600;
            font-size: 14px;
            color: {cls.TEXT_PRIMARY};
        }}
        #duration_label {{
            font-size: 12px;
            color: {cls.TEXT_PRIMARY};
            background: rgba(0,0,0,0.6);
            border-radius: 6px;
            padding: 2px 4px;
        }}
        #thumb_label {{
            border-radius: 6px;
            border: none;
            background: {cls.BACKGROUND_LIGHT};
        }}
        #author_label, #date_label {{
            font-size: 12px;
            color: {cls.TEXT_SECONDARY};
        }}
        QCheckBox::indicator {{
            width: 14px; height: 14px;
            border: 1px solid {cls.BORDER};
            border-radius: 3px;
        }}
        QCheckBox::indicator:checked {{
            background: {cls.PRIMARY};
            border: 1px solid {cls.PRIMARY};
        }}
        """

    @classmethod
    def sidebar_style(cls) -> str:
        return f"""
        #sidebar {{
            background: {cls.BACKGROUND_LIGHT};
            border-right: 1px solid {cls.BORDER};
            padding: 12px 0;
        }}
        #sidebar QPushButton {{
            background: transparent;
            color: {cls.TEXT_SECONDARY};
            border: none;
            text-align: left;
            padding: 8px 16px;
            font-size: 14px;
            border-radius: 6px;
            margin: 2px 6px;
        }}
        #sidebar QPushButton:hover {{
            background: {cls.SURFACE_HOVER};
            color: {cls.TEXT_PRIMARY};
        }}
        #sidebar QPushButton:checked {{
            background: {cls.PRIMARY};
            color: white;
        }}
        #sidebar QPushButton[active="true"] {{
            background: {cls.PRIMARY};
            color: white;
        }}
        """

# --- VIDEO CARD ---
class VideoCard(QFrame):
    watch_later_removed = pyqtSignal()
    video_removed = pyqtSignal(str)

    def __init__(self, video: Video, playlist_id: int = None, main_window=None):
        super().__init__()
        self.video = video
        self.playlist_id = playlist_id
        self.main_window = main_window
        self.thumbnail_loader = None
        self.thread_pool = QThreadPool.globalInstance()
        self.setFixedSize(280, 320)
        self.setStyleSheet(Theme.video_card_style())
        self._setup_ui()

    def _setup_ui(self):
        layout = QVBoxLayout(self)
        layout.setContentsMargins(12, 12, 12, 12)
        layout.setSpacing(8)
        self.thumb_label = QLabel()
        self.thumb_label.setObjectName("thumb_label")
        self.thumb_label.setFixedSize(256, 144)
        self.thumb_label.setAlignment(Qt.AlignCenter)
        self.duration_label = QLabel(f"⏱ {self._format_duration(self.video.duration)}", self.thumb_label)
        self.duration_label.setObjectName("duration_label")
        self.duration_label.move(224, 112)
        self.duration_label.setAlignment(Qt.AlignCenter)
        layout.addWidget(self.thumb_label)
        title_text = self.video.title[:40] + "..." if len(self.video.title) > 40 else self.video.title
        self.title_label = QLabel(title_text)
        self.title_label.setObjectName("title_label")
        self.title_label.setWordWrap(True)
        self.title_label.setToolTip(self.video.title)
        layout.addWidget(self.title_label)
        if hasattr(self.video, 'author') and self.video.author:
            self.author_label = QLabel(f"👤 {self.video.author}")
            self.author_label.setObjectName("author_label")
            layout.addWidget(self.author_label)
        if hasattr(self.video, 'published') and self.video.published:
            pub_date = self.video.published.strftime("%d/%m/%Y")
            self.date_label = QLabel(f"📅 {pub_date}")
            self.date_label.setObjectName("date_label")
            layout.addWidget(self.date_label)
        self.checkbox = QCheckBox()
        layout.addWidget(self.checkbox)
        self.setContextMenuPolicy(Qt.CustomContextMenu)
        self.customContextMenuRequested.connect(self.show_menu)
        if hasattr(self.video, 'thumbnail_url') and self.video.thumbnail_url:
            self.thumbnail_loader = ThumbnailLoader(self.video.thumbnail_url, self.thumb_label)
            self.thread_pool.start(self.thumbnail_loader)

    def _format_duration(self, seconds: str) -> str:
        try:
            sec = int(seconds)
            h, m, s = sec // 3600, (sec % 3600) // 60, sec % 60
            if h: return f"{h}h {m}m"
            elif m: return f"{m}m {s}s"
            return f"{s}s"
        except ValueError:
            return "0s"

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton and not self.checkbox.underMouse():
            webbrowser.open(self.video.url)

    def show_menu(self, pos):
        menu = QMenu(self)
        menu.setStyleSheet(f"""
            QMenu {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                border-radius: 6px;
                color: {Theme.TEXT_PRIMARY};
            }}
            QMenu::item:selected {{
                background: rgba(106, 90, 205, 0.2);
                border-radius: 3px;
            }}
        """)
        menu.addAction(QIcon.fromTheme("media-playback-start"), "Riproduci",
                      lambda: webbrowser.open(self.video.url))
        menu.addAction(QIcon.fromTheme("edit-copy"), "Copia link",
                      lambda: QApplication.clipboard().setText(self.video.url))
        menu.addAction(QIcon.fromTheme("document-save"), "Scarica video", self.download_video)
        playlist_menu = menu.addMenu(QIcon.fromTheme("view-media-playlist"), "Aggiungi a playlist")
        for pl in PlaylistService.get_playlists():
            if pl.name != "Watch Later":
                action = playlist_menu.addAction(pl.name)
                action.setIcon(QIcon.fromTheme("folder"))
                action.triggered.connect(lambda _, p=pl.id: self.add_to_playlist(p))
        if self.playlist_id is None:
            menu.addAction(QIcon.fromTheme("bookmark-new"), "Salva in Watch Later", self.toggle_watch_later)
        else:
            menu.addAction(QIcon.fromTheme("list-remove"), "Rimuovi da playlist", self.remove_from_current_playlist)
        menu.exec_(self.mapToGlobal(pos))

    def add_to_playlist(self, playlist_id: int):
        if PlaylistService.add_to_playlist(playlist_id, self.video):
            self.main_window.statusBar().showMessage(f"✓ Video aggiunto a {next(p.name for p in PlaylistService.get_playlists() if p.id == playlist_id)}")
        else:
            QMessageBox.warning(self, "Attenzione", "Video già presente in questa playlist")

    def toggle_watch_later(self):
        wl_playlist = PlaylistService.get_watch_later_playlist()
        if not wl_playlist:
            return
        existing_ids = {v.video_id for v in wl_playlist.videos}
        if self.video.video_id not in existing_ids:
            if PlaylistService.add_to_playlist(wl_playlist.id, self.video):
                QMessageBox.information(self, "Successo", "Video aggiunto a Watch Later")
            else:
                QMessageBox.warning(self, "Errore", "Impossibile aggiungere il video")
        else:
            if QMessageBox.question(
                self, "Attenzione", "Video già in Watch Later. Rimuovere?",
                QMessageBox.Yes | QMessageBox.No
            ) == QMessageBox.Yes:
                if PlaylistService.remove_from_playlist(wl_playlist.id, self.video.video_id):
                    self.watch_later_removed.emit()

    def remove_from_current_playlist(self):
        if self.playlist_id is not None:
            if PlaylistService.remove_from_playlist(self.playlist_id, self.video.video_id):
                self.video_removed.emit(self.video.video_id)

    def download_video(self):
        download_dir = QFileDialog.getExistingDirectory(self, "Seleziona cartella di destinazione", str(Path.home()))
        if not download_dir:
            return
        progress_dialog = QProgressDialog(f"Scaricamento: {self.video.title}", "Annulla", 0, 100, self)
        progress_dialog.setWindowTitle("Download in corso")
        progress_dialog.setWindowModality(Qt.WindowModal)
        progress_dialog.setAutoClose(False)

        def update_progress(progress):
            progress_dialog.setValue(progress)

        def on_completed(filename, title):
            progress_dialog.setValue(100)
            QMessageBox.information(self, "Download completato", f"Video salvato come: {filename}")
            progress_dialog.close()

        def on_failed(url, error):
            progress_dialog.close()
            QMessageBox.warning(self, "Errore", f"Impossibile scaricare il video: {error}")

        worker = DownloadWorker(self.video.url, download_dir)
        worker.signals.progress.connect(update_progress)
        worker.signals.finished.connect(on_completed)
        worker.signals.error.connect(on_failed)
        self.thread_pool.start(worker)
        progress_dialog.exec_()

# --- VIDEO GRID ---
class VideoGrid(QScrollArea):
    def __init__(self, main_window=None):
        super().__init__()
        self.main_window = main_window
        self.thread_pool = QThreadPool.globalInstance()
        self.setWidgetResizable(True)
        self.setStyleSheet(f"VideoGrid {{ background: {Theme.BACKGROUND}; border: none; }}")
        self.content = QWidget()
        self.content.setStyleSheet(f"background: {Theme.BACKGROUND};")
        self.layout = QGridLayout(self.content)
        self.layout.setSpacing(16)
        self.layout.setContentsMargins(16, 16, 16, 16)
        self.content.setLayout(self.layout)
        self.setWidget(self.content)
        self.video_cards = []
        self.current_page = 1
        self.total_pages = 1
        self.query = ""
        self.sort_by = "recent"
        self.playlist_id = None
        self.feed_id = None
        self.feed_items_cache = []
        self._setup_pagination()

    def _setup_pagination(self):
        self.pagination_widget = QWidget()
        self.pagination_layout = QHBoxLayout(self.pagination_widget)
        self.pagination_layout.setContentsMargins(0, 0, 0, 0)
        self.pagination_layout.setSpacing(12)
        self.prev_btn = QPushButton("‹")
        self.prev_btn.setFixedSize(36, 36)
        self.prev_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                border-radius: 18px;
                color: {Theme.TEXT_PRIMARY};
                font-size: 18px;
                font-weight: bold;
                padding: 0px;
            }}
            QPushButton:hover {{
                background: {Theme.PRIMARY};
                border: 1px solid {Theme.PRIMARY};
                color: white;
            }}
            QPushButton:disabled {{
                color: {Theme.TEXT_DISABLED};
                border: 1px solid {Theme.BORDER};
            }}
        """)
        self.next_btn = QPushButton("›")
        self.next_btn.setFixedSize(36, 36)
        self.next_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                border-radius: 18px;
                color: {Theme.TEXT_PRIMARY};
                font-size: 18px;
                font-weight: bold;
                padding: 0px;
            }}
            QPushButton:hover {{
                background: {Theme.PRIMARY};
                border: 1px solid {Theme.PRIMARY};
                color: white;
            }}
            QPushButton:disabled {{
                color: {Theme.TEXT_DISABLED};
                border: 1px solid {Theme.BORDER};
            }}
        """)
        self.page_label = QLabel("Pagina 1/1")
        self.page_label.setFixedHeight(36)
        self.page_label.setStyleSheet(f"""
            color: {Theme.TEXT_PRIMARY};
            font-family: 'Inter';
            font-size: 14px;
            padding: 0px 12px;
            qproperty-alignment: AlignCenter;
            background: {Theme.SURFACE};
            border: 1px solid {Theme.BORDER};
            border-radius: 6px;
            min-width: 100px;
        """)
        self.sort_combo = QComboBox()
        self.sort_combo.setFixedHeight(36)
        self.sort_combo.addItems(["Più recenti", "Più visti", "Durata", "Rilevanza"])
        self.sort_combo.setStyleSheet(f"""
            QComboBox {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                border-radius: 6px;
                color: {Theme.TEXT_PRIMARY};
                padding: 3px 8px;
                min-width: 120px;
            }}
            QComboBox::drop-down {{ border: 0px; }}
            QComboBox QAbstractItemView {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                color: {Theme.TEXT_PRIMARY};
                selection-background-color: {Theme.PRIMARY};
            }}
        """)
        self.delete_selected_btn = QPushButton("🗑️ Elimina selezionati")
        self.delete_selected_btn.setFixedHeight(36)
        self.delete_selected_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.DANGER};
                color: white;
                border: none;
                border-radius: 6px;
                padding: 4px 12px;
                font-size: 14px;
            }}
            QPushButton:hover {{ background: #ff5555; }}
        """)
        self.sort_combo.currentTextChanged.connect(self.change_sort)
        self.prev_btn.clicked.connect(self.prev_page)
        self.next_btn.clicked.connect(self.next_page)
        self.delete_selected_btn.clicked.connect(self.delete_selected_videos)
        self.pagination_layout.addWidget(self.prev_btn)
        self.pagination_layout.addWidget(self.page_label)
        self.pagination_layout.addWidget(self.next_btn)
        self.pagination_layout.addStretch()
        self.pagination_layout.addWidget(QLabel("Ordina per:"))
        self.pagination_layout.addWidget(self.sort_combo)
        self.pagination_layout.addWidget(self.delete_selected_btn)
        self.layout.addWidget(self.pagination_widget, 100, 0, 1, 4)
        self.delete_selected_btn.hide()

    def change_sort(self, text):
        self.sort_by = {
            "Più recenti": "recent",
            "Più visti": "views",
            "Durata": "duration",
            "Rilevanza": "relevance"
        }.get(text, "recent")
        if self.playlist_id is None and self.feed_id is None:
            self.load_page(1)

    def update_videos(self, videos: List[Video], query: str = "", total_results: int = 0,
                     page: int = 1, playlist_id: Optional[int] = None, feed_id: Optional[int] = None):
        self.query = query
        self.current_page = page
        self.playlist_id = playlist_id
        self.feed_id = feed_id
        for card in self.video_cards:
            if card.thumbnail_loader:
                card.thumbnail_loader.stop()
            card.deleteLater()
        self.video_cards.clear()
        columns = max(1, (self.width() - 24) // 300)
        for idx, video in enumerate(videos):
            card = VideoCard(video, playlist_id, self.main_window)
            card.video_removed.connect(self.on_video_removed)
            self.video_cards.append(card)
            row, col = divmod(idx, columns)
            self.layout.addWidget(card, row, col)
        if feed_id == -1:
            self.delete_selected_btn.hide()
            self.prev_btn.hide()
            self.next_btn.hide()
            self.sort_combo.hide()
            self.page_label.setText(f"Totale: {len(videos)} video dai feed RSS")
        elif playlist_id is not None or feed_id is not None:
            self.delete_selected_btn.show()
            self.prev_btn.setEnabled(False)
            self.next_btn.setEnabled(False)
            source = "playlist" if playlist_id else "feed"
            count = len(videos)
            self.page_label.setText(f"{count} video in {source}")
        else:
            self.delete_selected_btn.hide()
            self.prev_btn.setEnabled(self.current_page > 1)
            self.next_btn.setEnabled(self.current_page < self.total_pages)
            self.page_label.setText(f"Pagina {self.current_page}/{self.total_pages}")

    def prev_page(self):
        if self.current_page > 1:
            self.load_page(self.current_page - 1)

    def next_page(self):
        if self.current_page < self.total_pages:
            self.load_page(self.current_page + 1)

    def load_page(self, page: int):
        if page < 1 or page > self.total_pages:
            return
        if self.playlist_id is not None:
            videos = PlaylistService.get_playlist_videos(self.playlist_id)
            self.update_videos(videos, playlist_id=self.playlist_id)
        elif self.feed_id is not None and self.feed_id != -1:
            if not self.feed_items_cache:
                self.feed_items_cache = RSSService.get_feed_items(self.feed_id, limit=None)
            videos = [
                Video(
                    title=item.title,
                    url=item.url,
                    thumbnail_url=item.thumbnail_url,
                    duration=item.duration,
                    video_id=item.video_id,
                    platform=item.platform,
                    author=item.author,
                    published=item.published
                )
                for item in self.feed_items_cache
            ]
            self.update_videos(videos, playlist_id=None, feed_id=self.feed_id, page=1)
        else:
            videos, total_results = SearchService.search_videos(
                self.query, page=page, count=50, sort_by=self.sort_by
            )
            self.total_pages = max(1, (total_results + 49) // 50)
            self.update_videos(videos, self.query, total_results, page, self.playlist_id)

    def delete_selected_videos(self):
        selected_videos = []
        for card in self.video_cards:
            if card.checkbox.isChecked():
                selected_videos.append(card.video.video_id)
        if not selected_videos:
            QMessageBox.warning(self, "Attenzione", "Nessun video selezionato!")
            return
        if QMessageBox.question(
            self, "Conferma", f"Rimuovere {len(selected_videos)} video?",
            QMessageBox.Yes | QMessageBox.No
        ) == QMessageBox.Yes:
            if self.playlist_id is not None:
                for video_id in selected_videos:
                    PlaylistService.remove_from_playlist(self.playlist_id, video_id)
            elif self.feed_id is not None and self.feed_id != -1:
                QMessageBox.warning(self, "Attenzione", "Non puoi rimuovere singoli video da un feed. Rimuovi l'intero feed dalla gestione feed.")
                return
            self.refresh_videos()

    def refresh_videos(self):
        if self.playlist_id is not None:
            videos = PlaylistService.get_playlist_videos(self.playlist_id)
            self.update_videos(videos, playlist_id=self.playlist_id)
        elif self.feed_id is not None and self.feed_id != -1:
            self.feed_items_cache = RSSService.get_feed_items(self.feed_id, limit=None)
            videos = [
                Video(
                    title=item.title,
                    url=item.url,
                    thumbnail_url=item.thumbnail_url,
                    duration=item.duration,
                    video_id=item.video_id,
                    platform=item.platform,
                    author=item.author,
                    published=item.published
                )
                for item in self.feed_items_cache
            ]
            self.update_videos(videos, playlist_id=None, feed_id=self.feed_id)
        else:
            self.load_page(self.current_page)

    def on_video_removed(self, video_id):
        self.refresh_videos()

    def resizeEvent(self, event):
        super().resizeEvent(event)
        if self.video_cards:
            self.refresh_videos()

    def load_playlist_videos(self, playlist_id: int):
        self.playlist_id = playlist_id
        self.feed_id = None
        self.query = ""
        self.current_page = 1
        videos = PlaylistService.get_playlist_videos(playlist_id)
        self.update_videos(videos, playlist_id=playlist_id)

# --- PLAYLIST PANEL ---
class PlaylistPanel(QWidget):
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        self.setStyleSheet(f"background: {Theme.BACKGROUND};")
        layout = QVBoxLayout(self)
        layout.setContentsMargins(12, 12, 12, 12)
        self.playlist_list = QListWidget()
        self.playlist_list.setStyleSheet(f"""
            QListWidget {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                border-radius: 6px;
                color: {Theme.TEXT_PRIMARY};
                font-family: 'Inter';
                font-size: 14px;
                padding: 6px;
            }}
            QListWidget::item {{
                padding: 8px;
                border-radius: 4px;
            }}
            QListWidget::item:selected {{
                background: {Theme.PRIMARY};
                color: white;
            }}
            QListWidget::item:hover {{
                background: {Theme.SURFACE_HOVER};
            }}
        """)
        self.playlist_list.itemClicked.connect(self.show_videos)
        btn_widget = QWidget()
        btn_layout = QHBoxLayout(btn_widget)
        btn_layout.setContentsMargins(0, 0, 0, 0)
        add_btn = QPushButton("Nuova Playlist")
        add_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.PRIMARY};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 6px 12px;
                font-family: 'Inter';
            }}
            QPushButton:hover {{ background: {Theme.PRIMARY_HOVER}; }}
        """)
        remove_btn = QPushButton("Elimina Playlist")
        remove_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.DANGER};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 6px 12px;
                font-family: 'Inter';
            }}
            QPushButton:hover {{ background: #ff5555; }}
        """)
        btn_layout.addWidget(add_btn)
        btn_layout.addWidget(remove_btn)
        layout.addWidget(btn_widget)
        layout.addWidget(self.playlist_list)
        add_btn.clicked.connect(self.add_playlist)
        remove_btn.clicked.connect(self.remove_playlist)
        self.refresh_playlists()

    def refresh_playlists(self):
        self.playlist_list.clear()
        for pl in PlaylistService.get_playlists():
            item = QListWidgetItem(pl.name)
            item.setSizeHint(QSize(0, 32))
            self.playlist_list.addItem(item)

    def add_playlist(self):
        name, ok = QInputDialog.getText(self, "Nuova Playlist", "Nome:")
        if ok and name:
            try:
                pl = Playlist(name=name)
                PlaylistService.save_playlist(pl)
                self.refresh_playlists()
            except Exception as e:
                QMessageBox.critical(self, "Errore", f"Impossibile creare playlist: {e}")

    def remove_playlist(self):
        item = self.playlist_list.currentItem()
        if not item:
            return
        name = item.text()
        if PlaylistService.remove_playlist(name):
            self.refresh_playlists()
        else:
            QMessageBox.warning(self, "Attenzione", "Non puoi rimuovere questa playlist")

    def show_videos(self, item):
        pl_name = item.text()
        playlists = PlaylistService.get_playlists()
        pl = next((p for p in playlists if p.name == pl_name), None)
        if pl:
            self.main_window.show_view("search")
            self.main_window.video_grid.load_playlist_videos(pl.id)
            self.main_window.statusBar().showMessage(f"🎵 Playlist '{pl_name}' caricata ({len(PlaylistService.get_playlist_videos(pl.id))} video)")

# --- FEED MANAGER PANEL ---
class FeedManagerPanel(QWidget):
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        self.setStyleSheet(f"background: {Theme.BACKGROUND};")
        layout = QVBoxLayout(self)
        layout.setContentsMargins(12, 12, 12, 12)
        self.feed_search = QLineEdit()
        self.feed_search.setPlaceholderText("Incollare URL feed RSS PeerTube...")
        self.feed_search.setStyleSheet(f"""
            QLineEdit {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                border-radius: 6px;
                color: {Theme.TEXT_PRIMARY};
                padding: 8px;
                font-family: 'Inter';
            }}
        """)
        self.feed_search.returnPressed.connect(self.add_feed_from_url)
        add_feed_btn = QPushButton("Aggiungi Feed")
        add_feed_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.PRIMARY};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 8px 16px;
                font-family: 'Inter';
            }}
            QPushButton:hover {{ background: {Theme.PRIMARY_HOVER}; }}
        """)
        add_feed_btn.clicked.connect(self.add_feed_from_url)
        search_layout = QHBoxLayout()
        search_layout.addWidget(self.feed_search)
        search_layout.addWidget(add_feed_btn)
        self.feed_list = QListWidget()
        self.feed_list.setStyleSheet(f"""
            QListWidget {{
                background: {Theme.SURFACE};
                border: 1px solid {Theme.BORDER};
                border-radius: 6px;
                color: {Theme.TEXT_PRIMARY};
                font-family: 'Inter';
                font-size: 14px;
                padding: 6px;
            }}
            QListWidget::item {{
                padding: 8px;
                border-radius: 4px;
            }}
            QListWidget::item:selected {{
                background: {Theme.PRIMARY};
                color: white;
            }}
            QListWidget::item:hover {{
                background: {Theme.SURFACE_HOVER};
            }}
        """)
        self.feed_list.itemClicked.connect(self.show_feed_content)
        btn_widget = QWidget()
        btn_layout = QHBoxLayout(btn_widget)
        btn_layout.setContentsMargins(0, 0, 0, 0)
        refresh_btn = QPushButton("Aggiorna Tutti")
        refresh_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.PRIMARY};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 6px 12px;
                font-family: 'Inter';
            }}
            QPushButton:hover {{ background: {Theme.PRIMARY_HOVER}; }}
        """)
        remove_btn = QPushButton("Rimuovi Feed")
        remove_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.DANGER};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 6px 12px;
                font-family: 'Inter';
            }}
            QPushButton:hover {{ background: #ff5555; }}
        """)
        clear_all_btn = QPushButton("Cancella Tutti i Feed")
        clear_all_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.DANGER};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 6px 12px;
                font-family: 'Inter';
            }}
            QPushButton:hover {{ background: #ff2222; }}
        """)
        btn_layout.addWidget(refresh_btn)
        btn_layout.addWidget(remove_btn)
        btn_layout.addWidget(clear_all_btn)
        layout.addLayout(search_layout)
        layout.addWidget(self.feed_list)
        layout.addWidget(btn_widget)
        refresh_btn.clicked.connect(self.refresh_all_feeds)
        remove_btn.clicked.connect(self.remove_selected_feed)
        clear_all_btn.clicked.connect(self.clear_all_feeds)
        self.refresh_feed_list()

    def add_feed_from_url(self):
        url = self.feed_search.text().strip()
        if not url:
            QMessageBox.warning(self, "Attenzione", "Inserisci un URL valido")
            return
        try:
            if RSSService.add_feed(url):
                self.feed_search.clear()
                self.refresh_feed_list()
                QMessageBox.information(self, "Successo", "Feed aggiunto con successo!")
            else:
                QMessageBox.warning(self, "Errore", "Impossibile aggiungere il feed")
        except Exception as e:
            QMessageBox.critical(self, "Errore", f"Errore durante l'aggiunta del feed: {str(e)}")

    def refresh_feed_list(self):
        self.feed_list.clear()
        for feed in RSSService.get_feeds():
            item = QListWidgetItem()
            icon = QIcon.fromTheme("application-rss+xml")
            item.setIcon(icon)
            item_text = f"{feed.title} "
            if feed.is_channel:
                item_text += "👤 "
            else:
                item_text += "📋 "
            item_text += f"({len(RSSService.get_feed_items(feed.id, limit=None))} video)"
            if feed.last_updated:
                item_text += f"\nUltimo aggiornamento: {feed.last_updated.strftime('%d/%m/%Y %H:%M')}"
            item.setText(item_text)
            item.setData(Qt.UserRole, feed.id)
            item.setSizeHint(QSize(0, 50))
            self.feed_list.addItem(item)

    def show_feed_content(self, item):
        feed_id = item.data(Qt.UserRole)
        self.main_window.show_view("search")
        self.main_window.video_grid.feed_id = feed_id
        self.main_window.video_grid.feed_items_cache = RSSService.get_feed_items(feed_id, limit=None)
        self.main_window.video_grid.current_page = 1
        videos = [
            Video(
                title=item.title,
                url=item.url,
                thumbnail_url=item.thumbnail_url,
                duration=item.duration,
                video_id=item.video_id,
                platform=item.platform,
                author=item.author,
                published=item.published
            )
            for item in self.main_window.video_grid.feed_items_cache
        ]
        self.main_window.video_grid.update_videos(
            videos,
            query=f"Feed: {item.text().split('(')[0].strip()}",
            total_results=len(videos),
            page=1,
            feed_id=feed_id
        )
        self.main_window.statusBar().showMessage(f"📡 Feed caricato ({len(videos)} video)")

    def refresh_all_feeds(self):
        try:
            for feed in RSSService.get_feeds():
                RSSService.refresh_feed(feed.id)
            self.refresh_feed_list()
            QMessageBox.information(self, "Successo", "Tutti i feed sono stati aggiornati")
        except Exception as e:
            QMessageBox.warning(self, "Errore", f"Errore durante l'aggiornamento: {str(e)}")

    def remove_selected_feed(self):
        item = self.feed_list.currentItem()
        if not item:
            return
        feed_id = item.data(Qt.UserRole)
        if QMessageBox.question(
            self, "Conferma", "Rimuovere questo feed?",
            QMessageBox.Yes | QMessageBox.No
        ) == QMessageBox.Yes:
            if RSSService.remove_feed(feed_id):
                self.refresh_feed_list()
            else:
                QMessageBox.warning(self, "Errore", "Impossibile rimuovere il feed")

    def clear_all_feeds(self):
        if QMessageBox.question(
            self, "Conferma", "Rimuovere TUTTI i feed? Questa azione non può essere annullata.",
            QMessageBox.Yes | QMessageBox.No
        ) == QMessageBox.Yes:
            if RSSService.clear_all_feeds():
                self.refresh_feed_list()
                QMessageBox.information(self, "Successo", "Tutti i feed sono stati rimossi")
            else:
                QMessageBox.warning(self, "Errore", "Impossibile rimuovere i feed")

# --- FEED CONTENT TAB ---
class FeedContentTab(QWidget):
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        self.feed_grid = VideoGrid(main_window)
        btn_widget = QWidget()
        btn_layout = QHBoxLayout(btn_widget)
        btn_layout.setContentsMargins(0, 0, 0, 0)
        refresh_btn = QPushButton("Aggiorna tutti i feed")
        refresh_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.PRIMARY};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 8px 16px;
                margin: 8px;
            }}
            QPushButton:hover {{ background: {Theme.PRIMARY_HOVER}; }}
        """)
        clear_btn = QPushButton("Cancella tutti i feed")
        clear_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.DANGER};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 8px 16px;
                margin: 8px;
            }}
            QPushButton:hover {{ background: #ff2222; }}
        """)
        btn_layout.addWidget(refresh_btn)
        btn_layout.addWidget(clear_btn)
        layout.addWidget(btn_widget)
        layout.addWidget(self.feed_grid)
        refresh_btn.clicked.connect(self.refresh_all_content)
        clear_btn.clicked.connect(self.clear_all_feeds)

        # Connessione del segnale dalla sidebar per il refresh automatico
        self.main_window.sidebar.feed_content_clicked.connect(self.load_feed_content)
        self.load_feed_content()

    def load_feed_content(self):
        items = RSSService.get_all_feed_items(limit=None)
        videos = [
            Video(
                title=item.title,
                url=item.url,
                thumbnail_url=item.thumbnail_url,
                duration=item.duration,
                video_id=item.video_id,
                platform=item.platform,
                author=item.author,
                published=item.published
            )
            for item in items
        ]
        self.feed_grid.update_videos(
            videos,
            query="Tutti i feed RSS",
            total_results=len(videos),
            page=1,
            feed_id=-1
        )

    def refresh_all_content(self):
        try:
            for feed in RSSService.get_feeds():
                RSSService.refresh_feed(feed.id)
            self.load_feed_content()
            QMessageBox.information(self, "Successo", "Contenuti aggiornati!")
        except Exception as e:
            QMessageBox.warning(self, "Errore", f"Errore durante l'aggiornamento: {str(e)}")

    def clear_all_feeds(self):
        if QMessageBox.question(
            self, "Conferma", "Rimuovere TUTTI i feed? Questa azione non può essere annullata.",
            QMessageBox.Yes | QMessageBox.No
        ) == QMessageBox.Yes:
            if RSSService.clear_all_feeds():
                self.feed_grid.update_videos([], query="Nessun feed disponibile")
                self.feed_grid.page_label.setText("Nessun feed disponibile")
                QMessageBox.information(self, "Successo", "Tutti i feed sono stati rimossi")
            else:
                QMessageBox.warning(self, "Errore", "Impossibile rimuovere i feed")

# --- SETTINGS PANEL ---
class SettingsPanel(QWidget):
    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        self.setStyleSheet(f"background: {Theme.BACKGROUND};")
        layout = QVBoxLayout(self)
        layout.setContentsMargins(12, 12, 12, 12)
        title = QLabel("Impostazioni")
        title.setStyleSheet(f"""
            QLabel {{
                font-size: 18px;
                font-weight: bold;
                color: {Theme.TEXT_PRIMARY};
                margin-bottom: 16px;
            }}
        """)
        clear_data_btn = QPushButton("Cancella TUTTI i dati utente")
        clear_data_btn.setStyleSheet(f"""
            QPushButton {{
                background: {Theme.DANGER};
                color: white;
                border: none;
                border-radius: 4px;
                padding: 10px 20px;
                font-family: 'Inter';
                font-size: 14px;
            }}
            QPushButton:hover {{ background: #ff2222; }}
        """)
        clear_data_btn.clicked.connect(self.clear_all_user_data)
        layout.addWidget(title)
        layout.addWidget(clear_data_btn)
        layout.addStretch()

    def clear_all_user_data(self):
        if QMessageBox.question(
            self, "Conferma",
            "Questa azione cancellerà TUTTE le tue playlist (eccetto 'Watch Later'), "
            "tutti i feed RSS e le preferenze utente. \n\n"
            "Questa azione NON PUÒ essere annullata. \n\n"
            "Sei sicuro di voler continuare?",
            QMessageBox.Yes | QMessageBox.No
        ) == QMessageBox.Yes:
            if db_manager.clear_all_user_data():
                QMessageBox.information(self, "Successo", "Tutti i dati utente sono stati cancellati. L'applicazione verrà riavviata.")
                from PyQt5.QtCore import QProcess
                QApplication.quit()
                QProcess.startDetached(sys.executable, [sys.argv[0]])

# --- SIDEBAR NAVIGATION ---
class Sidebar(QWidget):
    view_changed = pyqtSignal(str)
    feed_content_clicked = pyqtSignal()  # Segnale per il refresh automatico

    def __init__(self, main_window):
        super().__init__()
        self.main_window = main_window
        self.setObjectName("sidebar")
        self.setStyleSheet(Theme.sidebar_style())
        self.setFixedWidth(200)
        layout = QVBoxLayout(self)
        layout.setContentsMargins(0, 0, 0, 0)
        layout.setSpacing(0)
        title = QLabel("PurpleTube Player")
        title.setStyleSheet(f"""
            QLabel {{
                font-size: 18px;
                font-weight: bold;
                color: {Theme.TEXT_PRIMARY};
                padding: 12px 16px;
                margin-bottom: 6px;
            }}
        """)
        layout.addWidget(title)
        self.buttons = {
            "search": QPushButton("🔍 Ricerca"),
            "playlist": QPushButton("🎵 Playlist"),
            "feed_manager": QPushButton("📡 Gestione Feed"),
            "feed_content": QPushButton("📰 Contenuti Feed"),
            "settings": QPushButton("⚙️ Impostazioni")
        }
        for btn in self.buttons.values():
            btn.setCheckable(True)
            btn.setStyleSheet(f"""
                QPushButton {{
                    background: transparent;
                    color: {Theme.TEXT_SECONDARY};
                    border: none;
                    text-align: left;
                    padding: 8px 16px;
                    font-size: 14px;
                    border-radius: 4px;
                    margin: 2px 6px;
                }}
                QPushButton:hover {{
                    background: {Theme.SURFACE_HOVER};
                    color: {Theme.TEXT_PRIMARY};
                }}
                QPushButton:checked {{
                    background: {Theme.PRIMARY};
                    color: white;
                }}
            """)
            btn.clicked.connect(self.on_button_clicked)
            layout.addWidget(btn)
        layout.addStretch()
        self.buttons["search"].setChecked(True)
        self.buttons["search"].setProperty("active", True)

    def on_button_clicked(self):
        sender = self.main_window.sender()
        for btn in self.buttons.values():
            btn.setChecked(False)
            btn.setProperty("active", False)
            btn.style().unpolish(btn)
            btn.style().polish(btn)
        sender.setChecked(True)
        sender.setProperty("active", True)
        sender.style().unpolish(sender)
        sender.style().polish(sender)
        view_name = None
        for name, btn in self.buttons.items():
            if btn is sender:
                view_name = name
                break

        if view_name == "feed_content":
            self.feed_content_clicked.emit()  # Emette il segnale quando "Contenuti Feed" è cliccato

        if view_name:
            self.view_changed.emit(view_name)

    def set_active_view(self, view_name):
        for btn_name, btn in self.buttons.items():
            if btn_name == view_name:
                btn.setChecked(True)
                btn.setProperty("active", True)
                btn.style().unpolish(btn)
                btn.style().polish(btn)
            else:
                btn.setChecked(False)
                btn.setProperty("active", False)
                btn.style().unpolish(btn)
                btn.style().polish(btn)

# --- MAIN WINDOW ---
class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowIcon(QIcon("purpletube.svg"))
        self.setWindowTitle("PurpleTube Player")
        self.resize(1200, 800)
        self.setStyleSheet(Theme.global_stylesheet())
        for toolbar in self.findChildren(QToolBar):
            toolbar.hide()
        self.statusBar().setStyleSheet(f"""
            QStatusBar {{
                background: {Theme.SURFACE};
                color: {Theme.TEXT_SECONDARY};
                font-family: 'Inter';
                padding: 6px;
            }}
        """)
        central_widget = QWidget()
        main_layout = QHBoxLayout(central_widget)
        main_layout.setContentsMargins(0, 0, 0, 0)
        main_layout.setSpacing(0)
        self.sidebar = Sidebar(self)
        main_layout.addWidget(self.sidebar)
        content_widget = QWidget()
        content_layout = QVBoxLayout(content_widget)
        content_layout.setContentsMargins(12, 12, 12, 12)
        content_layout.setSpacing(12)
        self.stacked_widget = QStackedWidget()
        self.video_grid = VideoGrid(self)
        self.playlist_panel = PlaylistPanel(self)
        self.feed_manager = FeedManagerPanel(self)
        self.feed_content_tab = FeedContentTab(self)
        self.settings_panel = SettingsPanel(self)
        self.stacked_widget.addWidget(self.video_grid)
        self.stacked_widget.addWidget(self.playlist_panel)
        self.stacked_widget.addWidget(self.feed_manager)
        self.stacked_widget.addWidget(self.feed_content_tab)
        self.stacked_widget.addWidget(self.settings_panel)
        search_widget = self._create_search_widget()
        content_layout.addWidget(search_widget)
        content_layout.addWidget(self.stacked_widget)
        main_layout.addWidget(content_widget, stretch=1)
        self.setCentralWidget(central_widget)
        self.sidebar.view_changed.connect(self.show_view)
        self.show_view("search")
        self._create_menu_bar()

    def _create_search_widget(self):
        search_widget = QWidget()
        search_layout = QHBoxLayout(search_widget)
        search_layout.setContentsMargins(0, 0, 0, 0)
        search_layout.setSpacing(8)
        self.search_bar = QLineEdit()
        self.search_bar.setPlaceholderText("Cerca su SepiaSearch (es: 'linux')...")
        self.search_bar.setFixedHeight(32)
        self.search_bar.setStyleSheet(Theme.search_bar_style())
        search_btn = QPushButton("Cerca")
        search_btn.setFixedHeight(32)
        search_btn.setStyleSheet(Theme.global_stylesheet())
        search_btn.clicked.connect(self.search)
        self.search_bar.returnPressed.connect(self.search)
        search_layout.addWidget(self.search_bar)
        search_layout.addWidget(search_btn)
        return search_widget

    def _create_menu_bar(self):
        menu_bar = self.menuBar()
        file_menu = menu_bar.addMenu("&File")
        exit_action = QAction("Esci", self)
        exit_action.triggered.connect(QApplication.quit)
        file_menu.addAction(exit_action)
        edit_menu = menu_bar.addMenu("&Modifica")
        clear_data_action = QAction("Cancella tutti i dati utente", self)
        clear_data_action.triggered.connect(self.settings_panel.clear_all_user_data)
        edit_menu.addAction(clear_data_action)
        help_menu = menu_bar.addMenu("&Aiuto")
        about_action = QAction("Informazioni", self)
        about_action.triggered.connect(self.show_about)
        help_menu.addAction(about_action)

    def show_view(self, view_name):
        self.sidebar.set_active_view(view_name)
        view_index = {
            "search": 0,
            "playlist": 1,
            "feed_manager": 2,
            "feed_content": 3,
            "settings": 4
        }.get(view_name, 0)
        self.stacked_widget.setCurrentIndex(view_index)
        if view_name == "search":
            if not self.video_grid.query and self.video_grid.feed_id is None and self.video_grid.playlist_id is None:
                self.video_grid.load_page(1)

    def search(self):
        query = self.search_bar.text().strip()
        if not query:
            self.statusBar().showMessage("Inserisci un termine di ricerca...")
            return
        self.statusBar().showMessage(f"🔍 Cercando '{query}'...")
        videos, total_results = SearchService.search_videos(
            query, page=1, count=50, sort_by=self.video_grid.sort_by
        )
        self.video_grid.total_pages = max(1, (total_results + 49) // 50)
        self.video_grid.update_videos(
            videos, query, total_results, page=1
        )
        self.statusBar().showMessage(
            f"📊 Trovati {len(videos)} video per '{query}' "
            f"(pagina 1/{self.video_grid.total_pages})"
        )

    def show_about(self):
        about_text = """
        <h2>PurpleTube Player</h2>
        <p>Un lanciatore video open source per contenuti di PeerTube decentralizzati, progettato per promuovere la libertà digitale e l'accesso etico ai media.</p>
        <p><strong>Versione:</strong> 1.0</p>
        <p><strong>Licenza:</strong> <a href="https://www.gnu.org/licenses/gpl-3.0.en.html">GNU GPL v3</a></p>
        <p><strong>Sviluppatore:</strong> Angelo Massaro</p>
        <p>Per segnalare bug o richiedere informazioni, si prega di contattare: <a href="mailto:amassaro@boostmedia.it">amassaro@boostmedia.it</a></p>
        <p>Parte del progetto <a href="https://boostmedia.it/">BoostMedia APS</a>, un'iniziativa per la promozione di strumenti digitali etici e open source.</p>
        """
        QMessageBox.about(self, "Informazioni su PurpleTube Player", about_text)

# --- MAIN ---
if __name__ == "__main__":
    app = QApplication(sys.argv)
    font = QFont()
    font.setFamily("Inter")
    font.setPointSize(10)
    app.setFont(font)
    palette = QPalette()
    palette.setColor(QPalette.Window, QColor(15, 15, 15))
    palette.setColor(QPalette.Base, QColor(35, 35, 35))
    palette.setColor(QPalette.AlternateBase, QColor(50, 50, 50))
    palette.setColor(QPalette.WindowText, Qt.white)
    palette.setColor(QPalette.Text, Qt.white)
    palette.setColor(QPalette.ButtonText, Qt.white)
    palette.setColor(QPalette.ToolTipText, Qt.white)
    palette.setColor(QPalette.Button, QColor(30, 30, 30))
    palette.setColor(QPalette.Highlight, QColor(106, 90, 205))
    palette.setColor(QPalette.HighlightedText, Qt.white)
    palette.setColor(QPalette.Link, QColor(106, 90, 205))
    palette.setColor(QPalette.BrightText, QColor(255, 204, 0))
    palette.setColor(QPalette.ToolTipBase, QColor(60, 60, 60))
    palette.setColor(QPalette.ToolTipText, Qt.white)
    app.setPalette(palette)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())

