"""Download Zoom meeting transcripts via Server-to-Server OAuth"""

# AUTOGENERATED! DO NOT EDIT! File to edit: ../nbs/02_zoom.ipynb.

# %% auto 0
__all__ = ['HTTP_TIMEOUT', 'get_zoom_token', 'list_recordings', 'download_transcript', 'make_filename', 'main']

# %% ../nbs/02_zoom.ipynb 3
import os
import base64
from datetime import datetime, timedelta
from pathlib import Path
from typing import Optional, Annotated
from dotenv import load_dotenv
from fastcore.parallel import parallel
import httpx
import typer

# %% ../nbs/02_zoom.ipynb 4
load_dotenv()
HTTP_TIMEOUT = 15.0

# %% ../nbs/02_zoom.ipynb 6
def get_zoom_token() -> str:
    "Get Zoom access token using Server-to-Server OAuth."
    cid = os.environ["ZOOM_CLIENT_ID"]
    secret = os.environ["ZOOM_CLIENT_SECRET"]
    account = os.environ["ZOOM_ACCOUNT_ID"]
    
    encoded = base64.b64encode(f"{cid}:{secret}".encode()).decode()
    response = httpx.post(
        "https://zoom.us/oauth/token",
        params={"grant_type": "account_credentials", "account_id": account},
        headers={"Authorization": f"Basic {encoded}"},
        timeout=HTTP_TIMEOUT
    )
    response.raise_for_status()
    return response.json()["access_token"]

# %% ../nbs/02_zoom.ipynb 9
def list_recordings(days: int = 45) -> list[dict]:
    "List meetings with recordings from the last N days."
    token = get_zoom_token()
    to_date = datetime.now()
    from_date = to_date - timedelta(days=days)
    
    params = {
        "from": from_date.strftime("%Y-%m-%d"),
        "to": to_date.strftime("%Y-%m-%d"),
        "page_size": 300
    }
    
    all_meetings = []
    url = "https://api.zoom.us/v2/users/me/recordings"
    headers = {"Authorization": f"Bearer {token}"}
    
    while True:
        response = httpx.get(url, headers=headers, params=params, timeout=HTTP_TIMEOUT)
        response.raise_for_status()
        data = response.json()
        all_meetings.extend(data.get("meetings", []))
        
        if "next_page_token" in data and data["next_page_token"]:
            params["next_page_token"] = data["next_page_token"]
        else:
            break
    
    return all_meetings

# %% ../nbs/02_zoom.ipynb 12
def download_transcript(meeting_id: str, token: str) -> str | None:
    "Download transcript for a meeting ID."
    url = f"https://api.zoom.us/v2/meetings/{meeting_id}/recordings"
    response = httpx.get(url, headers={"Authorization": f"Bearer {token}"}, timeout=HTTP_TIMEOUT)
    response.raise_for_status()
    
    for file in response.json().get("recording_files", []):
        if file.get("file_type") == "TRANSCRIPT":
            transcript = httpx.get(
                file["download_url"],
                params={"access_token": token},
                follow_redirects=True,
                timeout=HTTP_TIMEOUT
            )
            transcript.raise_for_status()
            return transcript.text
    
    return None

# %% ../nbs/02_zoom.ipynb 15
def make_filename(meeting: dict) -> str:
    "Generate safe filename for a meeting transcript."
    date = meeting['start_time'].split('T')[0]
    topic = meeting.get('topic', 'Meeting')
    safe_topic = "".join(c for c in topic.replace(' ', '-') if c.isalnum() or c in " -_").strip()[:50]
    return f"{date}-{safe_topic}-{meeting['id']}.vtt"

# %% ../nbs/02_zoom.ipynb 19
def main(
    meeting_id: str = typer.Argument(None, help="Meeting ID to download"),
    search: str = typer.Option(None, "--search", "-s", help="Filter by text in topic"),
    days: int = typer.Option(45, "--days", "-d", help="Number of days to look back"),
    output: Path = typer.Option(None, "--output", "-o", help="Output file or directory"),
):
    """Download Zoom meeting transcripts.
    
    Examples:
      zoom.py 123456789              # Print to stdout (pipe to other tools)
      zoom.py 123456789 -o file.vtt  # Download to file
      zoom.py -s "Jason"              # Search, select one or 'a' for all
      zoom.py -s ""                   # List all meetings
    """
    try:
        token = get_zoom_token()
        
        # Direct meeting ID download
        if meeting_id:
            transcript = download_transcript(meeting_id, token)
            if not transcript:
                print("No transcript available.")
                raise typer.Exit(1)
            
            if output:
                output.parent.mkdir(parents=True, exist_ok=True)
                output.write_text(transcript, encoding="utf-8")
                print(f"Saved to {output}")
            else:
                print(transcript)
            return
        
        # Search and download
        meetings = list_recordings(days)
        
        # Filter by topic
        if search is not None:
            query = search.lower()
            meetings = [m for m in meetings if query in m.get('topic', '').lower()]
        
        if not meetings:
            print("No meetings found.")
            return
        
        # Show list
        print(f"\nFound {len(meetings)} meeting(s):\n")
        for idx, meeting in enumerate(meetings, 1):
            date = meeting['start_time'].split('T')[0]
            print(f"{idx:2}. {date} | {meeting['id']} | {meeting.get('topic', '')}")
        
        # Prompt for selection
        choice = typer.prompt("\nEnter number (or 'a' for all)")
        
        # Prompt for output directory
        outdir = Path(typer.prompt("Save to directory", default="."))
        if outdir != Path("."):
            outdir.mkdir(parents=True, exist_ok=True)
        
        # Download all
        if choice.lower() == "a":
            print(f"\nDownloading {len(meetings)} transcript(s)...")
            
            def download_one(meeting):
                transcript = download_transcript(str(meeting['id']), token)
                if transcript:
                    filepath = outdir / make_filename(meeting)
                    filepath.write_text(transcript, encoding="utf-8")
                    print(f"✓ {filepath.name}")
                else:
                    print(f"✗ No transcript: {meeting.get('topic', '')[:50]}")
            
            parallel(download_one, meetings, threadpool=True, n_workers=8)
            return
        
        # Download one
        try:
            idx = int(choice)
        except ValueError:
            print("Invalid input.")
            raise typer.Exit(1)
        
        if idx < 1 or idx > len(meetings):
            print("Invalid selection.")
            raise typer.Exit(1)
        
        meeting = meetings[idx - 1]
        transcript = download_transcript(str(meeting['id']), token)
        if not transcript:
            print("No transcript available.")
            raise typer.Exit(1)
        
        filepath = outdir / make_filename(meeting)
        filepath.write_text(transcript, encoding="utf-8")
        print(f"Saved to {filepath}")
        
    except (httpx.HTTPError, httpx.RequestError, KeyError) as e:
        print(f"Error: {e}")
        raise typer.Exit(1)
