"""Module d'upload vers YouTube."""

from pathlib import Path
from typing import Optional

from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.http import MediaFileUpload

import config


class YouTubeUploader:
    """Gère l'upload de vidéos sur YouTube."""

    def __init__(self):
        self.service = None
        self.creds = None

    def authenticate(self) -> bool:
        """Authentification OAuth2 avec YouTube API."""
        self.creds = None

        # Charger le token existant s'il existe
        if config.YOUTUBE_TOKEN_FILE.exists():
            self.creds = Credentials.from_authorized_user_file(
                str(config.YOUTUBE_TOKEN_FILE), config.YOUTUBE_SCOPES
            )

        # Rafraîchir ou créer de nouvelles credentials
        if not self.creds or not self.creds.valid:
            if self.creds and self.creds.expired and self.creds.refresh_token:
                self.creds.refresh(Request())
            else:
                # Essayer d'abord les credentials YouTube dédiées
                creds_file = config.YOUTUBE_CREDENTIALS_FILE
                if not creds_file.exists():
                    # Fallback sur les credentials Gmail (même projet GCP)
                    creds_file = config.CREDENTIALS_FILE

                if not creds_file.exists():
                    raise FileNotFoundError(
                        f"Aucun fichier credentials trouvé. "
                        f"Attendu: {config.YOUTUBE_CREDENTIALS_FILE} ou {config.CREDENTIALS_FILE}"
                    )

                flow = InstalledAppFlow.from_client_secrets_file(
                    str(creds_file), config.YOUTUBE_SCOPES
                )
                self.creds = flow.run_local_server(port=0)

            # Sauvegarder le token
            with open(config.YOUTUBE_TOKEN_FILE, "w") as token:
                token.write(self.creds.to_json())

        self.service = build("youtube", "v3", credentials=self.creds)
        return True

    def upload_video(
        self,
        video_path: Path,
        title: str,
        description: str,
        tags: Optional[list[str]] = None,
        category_id: Optional[str] = None,
        privacy_status: Optional[str] = None,
    ) -> dict:
        """Upload une vidéo sur YouTube."""
        if not self.service:
            raise RuntimeError("Non authentifié. Appelez authenticate() d'abord.")

        if not video_path.exists():
            raise FileNotFoundError(f"Fichier vidéo non trouvé: {video_path}")

        tags = tags or config.YOUTUBE_DEFAULT_TAGS
        category_id = category_id or config.YOUTUBE_CATEGORY_ID
        privacy_status = privacy_status or config.YOUTUBE_VISIBILITY

        # Métadonnées de la vidéo
        body = {
            "snippet": {
                "title": title[:100],  # Limite YouTube
                "description": description[:5000],  # Limite YouTube
                "tags": tags[:500],  # Limite YouTube
                "categoryId": category_id,
            },
            "status": {
                "privacyStatus": privacy_status,
                "selfDeclaredMadeForKids": False,
            },
        }

        # Préparer le fichier média
        media = MediaFileUpload(
            str(video_path),
            mimetype="audio/mpeg",  # Pour les fichiers MP3
            resumable=True,
        )

        # Upload
        request = self.service.videos().insert(
            part="snippet,status",
            body=body,
            media_body=media,
        )

        response = None
        while response is None:
            status, response = request.next_chunk()
            if status:
                print(f"Upload en cours: {int(status.progress() * 100)}%")

        video_id = response.get("id")
        video_url = f"https://www.youtube.com/watch?v={video_id}"

        return {
            "video_id": video_id,
            "url": video_url,
            "title": response["snippet"]["title"],
            "status": response["status"]["privacyStatus"],
        }

    def upload_audio_as_video(
        self,
        audio_path: Path,
        title: str,
        description: str,
        thumbnail_path: Optional[Path] = None,
        tags: Optional[list[str]] = None,
        privacy_status: Optional[str] = None,
    ) -> dict:
        """
        Upload un fichier audio comme vidéo YouTube.

        Note: YouTube n'accepte pas directement les fichiers audio.
        Cette méthode tente l'upload mais peut échouer.
        Pour une vraie vidéo, il faudrait convertir l'audio en vidéo
        avec ffmpeg (ajouter une image statique).
        """
        # Note: Cette méthode suppose que le fichier est déjà
        # une vidéo ou que YouTube accepte le format.
        # En production, utiliser ffmpeg pour créer une vraie vidéo.
        return self.upload_video(
            video_path=audio_path,
            title=title,
            description=description,
            tags=tags,
            privacy_status=privacy_status,
        )

    def get_channel_info(self) -> dict:
        """Récupère les informations de la chaîne YouTube."""
        if not self.service:
            raise RuntimeError("Non authentifié. Appelez authenticate() d'abord.")

        request = self.service.channels().list(part="snippet,statistics", mine=True)
        response = request.execute()

        if not response.get("items"):
            return {"error": "Aucune chaîne trouvée"}

        channel = response["items"][0]
        return {
            "id": channel["id"],
            "title": channel["snippet"]["title"],
            "description": channel["snippet"].get("description", ""),
            "subscribers": channel["statistics"].get("subscriberCount", "N/A"),
            "videos": channel["statistics"].get("videoCount", "0"),
        }

    def list_recent_videos(self, max_results: int = 5) -> list[dict]:
        """Liste les vidéos récentes de la chaîne."""
        if not self.service:
            raise RuntimeError("Non authentifié. Appelez authenticate() d'abord.")

        # D'abord, obtenir l'ID de la chaîne
        channel_response = (
            self.service.channels()
            .list(part="contentDetails", mine=True)
            .execute()
        )

        if not channel_response.get("items"):
            return []

        uploads_playlist_id = channel_response["items"][0]["contentDetails"][
            "relatedPlaylists"
        ]["uploads"]

        # Récupérer les vidéos de la playlist uploads
        videos_response = (
            self.service.playlistItems()
            .list(
                part="snippet",
                playlistId=uploads_playlist_id,
                maxResults=max_results,
            )
            .execute()
        )

        videos = []
        for item in videos_response.get("items", []):
            snippet = item["snippet"]
            videos.append(
                {
                    "video_id": snippet["resourceId"]["videoId"],
                    "title": snippet["title"],
                    "published_at": snippet["publishedAt"],
                    "url": f"https://www.youtube.com/watch?v={snippet['resourceId']['videoId']}",
                }
            )

        return videos
