#!/usr/bin/env python3
"""
MiniMax API client - shared HTTP utilities for all MiniMax generation tasks.

Handles authentication, API calls, async task polling, and file downloads.
Base URL: https://api.minimax.io/v1
Auth: Bearer token via MINIMAX_API_KEY environment variable.
"""

import json
import os
import sys
import time
from pathlib import Path
from typing import Dict, Any, Optional

try:
    import requests
except ImportError:
    print("Error: requests package not installed")
    print("Install with: pip install requests")
    sys.exit(1)

# Import centralized environment resolver
CLAUDE_ROOT = Path(__file__).parent.parent.parent.parent
sys.path.insert(0, str(CLAUDE_ROOT / 'scripts'))
try:
    from resolve_env import resolve_env
    CENTRALIZED_RESOLVER_AVAILABLE = True
except ImportError:
    CENTRALIZED_RESOLVER_AVAILABLE = False

BASE_URL = "https://api.minimax.io/v1"


def find_minimax_api_key() -> Optional[str]:
    """Find MINIMAX_API_KEY using centralized resolver or environment."""
    if CENTRALIZED_RESOLVER_AVAILABLE:
        return resolve_env('MINIMAX_API_KEY', skill='ai-multimodal')

    # Fallback: check environment and .env files
    api_key = os.getenv('MINIMAX_API_KEY')
    if api_key:
        return api_key

    # Check .env files in skill directory hierarchy
    try:
        from dotenv import load_dotenv
        skill_dir = Path(__file__).parent.parent
        for env_path in [skill_dir / '.env', skill_dir.parent / '.env']:
            if env_path.exists():
                load_dotenv(env_path, override=True)
        api_key = os.getenv('MINIMAX_API_KEY')
        if api_key:
            return api_key
    except ImportError:
        pass

    return None


def get_headers(api_key: str) -> Dict[str, str]:
    """Build authorization headers for MiniMax API."""
    return {
        "Authorization": f"Bearer {api_key}",
        "Content-Type": "application/json"
    }


def api_post(endpoint: str, payload: Dict[str, Any], api_key: str,
             verbose: bool = False, timeout: int = 120) -> Dict[str, Any]:
    """Make POST request to MiniMax API with error handling."""
    url = f"{BASE_URL}/{endpoint}"
    headers = get_headers(api_key)

    if verbose:
        print(f"  POST {url}", file=sys.stderr)

    response = requests.post(url, headers=headers, json=payload, timeout=timeout)

    if response.status_code != 200:
        raise Exception(
            f"MiniMax API error (HTTP {response.status_code}): {response.text}"
        )

    data = response.json()

    # Check MiniMax-specific error codes
    base_resp = data.get("base_resp", {})
    status_code = base_resp.get("status_code", 0)
    if status_code != 0:
        raise Exception(
            f"MiniMax API error (code {status_code}): "
            f"{base_resp.get('status_msg', 'Unknown error')}"
        )

    return data


def api_get(endpoint: str, params: Dict[str, str], api_key: str,
            verbose: bool = False) -> Dict[str, Any]:
    """Make GET request to MiniMax API."""
    url = f"{BASE_URL}/{endpoint}"
    headers = get_headers(api_key)

    if verbose:
        print(f"  GET {url}", file=sys.stderr)

    response = requests.get(url, headers=headers, params=params, timeout=60)

    if response.status_code != 200:
        raise Exception(
            f"MiniMax API error (HTTP {response.status_code}): {response.text}"
        )

    return response.json()


def poll_async_task(task_id: str, task_type: str, api_key: str,
                    poll_interval: int = 10, max_wait: int = 600,
                    verbose: bool = False) -> Dict[str, Any]:
    """Poll async task (video/music) until completion.

    Args:
        task_id: The task ID returned from creation endpoint
        task_type: 'video_generation' or 'music_generation'
        poll_interval: Seconds between polls (default 10)
        max_wait: Maximum wait time in seconds (default 600)
    """
    elapsed = 0
    while elapsed < max_wait:
        result = api_get(
            f"query/{task_type}",
            {"task_id": task_id},
            api_key,
            verbose=False
        )

        status = result.get("status", "Unknown")
        if verbose and elapsed > 0 and elapsed % 30 == 0:
            print(f"  Polling... {elapsed}s elapsed, status: {status}",
                  file=sys.stderr)

        if status == "Success":
            return result
        elif status in ("Failed", "Error"):
            raise Exception(f"Task failed: {json.dumps(result)}")

        time.sleep(poll_interval)
        elapsed += poll_interval

    raise TimeoutError(f"Task {task_id} timed out after {max_wait}s")


def download_file(file_id: str, api_key: str, output_path: str,
                  verbose: bool = False) -> str:
    """Download file from MiniMax file service."""
    result = api_get("files/retrieve", {"file_id": file_id}, api_key, verbose)

    download_url = result.get("file", {}).get("download_url")
    if not download_url:
        raise Exception(f"No download URL in response: {json.dumps(result)}")

    if verbose:
        print(f"  Downloading to: {output_path}", file=sys.stderr)

    response = requests.get(download_url, stream=True, timeout=300)
    response.raise_for_status()

    Path(output_path).parent.mkdir(parents=True, exist_ok=True)
    with open(output_path, 'wb') as f:
        for chunk in response.iter_content(chunk_size=8192):
            f.write(chunk)

    return output_path


def get_output_dir() -> Path:
    """Get project output directory for generated assets."""
    script_dir = Path(__file__).parent
    for parent in [script_dir] + list(script_dir.parents):
        if (parent / '.git').exists() or (parent / '.claude').exists():
            output_dir = parent / 'docs' / 'assets'
            output_dir.mkdir(parents=True, exist_ok=True)
            return output_dir
    # Fallback
    output_dir = script_dir.parent / 'assets'
    output_dir.mkdir(parents=True, exist_ok=True)
    return output_dir
