#!/usr/bin/env python3
"""
MTGJSON Data Downloader

Downloads MTGJSON data files into the container for loading.
Handles decompression of gzip files and unzipping of zip files.

Usage:
    python download_mtgjson_data.py
"""

import asyncio
import json
import gzip
import logging
import os
import sys
import zipfile
from pathlib import Path
from urllib.request import urlretrieve, urlopen

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

# MTGJSON download URLs
MTGJSON_BASE_URL = "https://mtgjson.com/api/5x"
MTGJSON_FILES = {
    "AllPrintings.psql.gz": "AllPrintings.psql.gz",
    "AllSetFiles.zip": "AllSetFiles.zip",
    "AllDeckFiles.zip": "AllDeckFiles.zip",
    "AllIdentifiers.json.gz": "AllIdentifiers.json.gz",
    "CardTypes.json.gz": "CardTypes.json.gz",
    "DeckList.json.gz": "DeckList.json.gz",
    "Keywords.json.gz": "Keywords.json.gz",
    "SetList.json.gz": "SetList.json.gz",
}


def download_file(url, dest_dir, filename):
    """Download a file from URL to destination directory"""
    dest_path = dest_dir / filename
    if dest_path.exists():
        logger.info(f"{filename} already exists, skipping download")
        return True
    
    logger.info(f"Downloading {filename}...")
    try:
        urlretrieve(url, dest_path)
        logger.info(f"Downloaded {filename} to {dest_path}")
        return True
    except Exception as e:
        logger.error(f"Failed to download {filename}: {e}")
        return False


def extract_zip(zip_path, dest_dir):
    """Extract a zip file to destination directory"""
    logger.info(f"Extracting {zip_path.name} to {dest_dir}...")
    try:
        with zipfile.ZipFile(zip_path, 'r') as zip_ref:
            zip_ref.extractall(dest_dir)
        logger.info(f"Extracted {zip_path.name} successfully")
        # Remove the zip file after extraction
        zip_path.unlink()
        return True
    except Exception as e:
        logger.error(f"Failed to extract {zip_path}: {e}")
        return False


def extract_gzip(gz_path, dest_path=None):
    """Extract a gzip file"""
    if not dest_path:
        dest_path = gz_path.with_suffix('')
    
    logger.info(f"Extracting {gz_path.name} to {dest_path}...")
    try:
        with gzip.open(gz_path, 'rt', encoding='utf-8') as f_in:
            with open(dest_path, 'w', encoding='utf-8') as f_out:
                f_out.write(f_in.read())
        logger.info(f"Extracted {gz_path.name} to {dest_path}")
        # Remove the gz file after extraction
        gz_path.unlink()
        return True
    except Exception as e:
        logger.error(f"Failed to extract {gz_path}: {e}")
        return False


async def download_all():
    """Download and extract all MTGJSON data files"""
    logger.info("Starting MTGJSON data download...")
    
    # Create data directory
    data_dir = Path("/app/data/mtgjson")
    data_dir.mkdir(parents=True, exist_ok=True)
    
    # Download AllPrintings.psql.gz
    if download_file(MTGJSON_BASE_URL + "/AllPrintings.psql.gz", data_dir, "AllPrintings.psql.gz"):
        # Extract gzip
        gz_path = data_dir / "AllPrintings.psql.gz"
        if extract_gzip(gz_path, data_dir / "AllPrintings.psql"):
            logger.info("AllPrintings.psql extracted successfully")
    
    # Download AllSetFiles.zip
    if download_file(MTGJSON_BASE_URL + "/AllSetFiles.zip", data_dir, "AllSetFiles.zip"):
        zip_path = data_dir / "AllSetFiles.zip"
        allsetfiles_dir = data_dir / "allsetfiles"
        allsetfiles_dir.mkdir(exist_ok=True)
        if extract_zip(zip_path, allsetfiles_dir):
            logger.info("AllSetFiles extracted successfully")
    
    # Download AllDeckFiles.zip
    if download_file(MTGJSON_BASE_URL + "/AllDeckFiles.zip", data_dir, "AllDeckFiles.zip"):
        zip_path = data_dir / "AllDeckFiles.zip"
        alldeckfiles_dir = data_dir / "alldeckfiles"
        alldeckfiles_dir.mkdir(exist_ok=True)
        if extract_zip(zip_path, alldeckfiles_dir):
            logger.info("AllDeckFiles extracted successfully")
    
    # Download AllIdentifiers.json.gz
    if download_file(MTGJSON_BASE_URL + "/AllIdentifiers.json.gz", data_dir, "AllIdentifiers.json.gz"):
        gz_path = data_dir / "AllIdentifiers.json.gz"
        if extract_gzip(gz_path, data_dir / "AllIdentifiers.json"):
            logger.info("AllIdentifiers.json extracted successfully")
    
    # Download CardTypes.json.gz
    if download_file(MTGJSON_BASE_URL + "/CardTypes.json.gz", data_dir, "CardTypes.json.gz"):
        gz_path = data_dir / "CardTypes.json.gz"
        if extract_gzip(gz_path, data_dir / "CardTypes.json"):
            logger.info("CardTypes.json extracted successfully")
    
    # Download DeckList.json.gz
    if download_file(MTGJSON_BASE_URL + "/DeckList.json.gz", data_dir, "DeckList.json.gz"):
        gz_path = data_dir / "DeckList.json.gz"
        if extract_gzip(gz_path, data_dir / "DeckList.json"):
            logger.info("DeckList.json extracted successfully")
    
    # Download Keywords.json.gz
    if download_file(MTGJSON_BASE_URL + "/Keywords.json.gz", data_dir, "Keywords.json.gz"):
        gz_path = data_dir / "Keywords.json.gz"
        if extract_gzip(gz_path, data_dir / "Keywords.json"):
            logger.info("Keywords.json extracted successfully")
    
    # Download SetList.json.gz
    if download_file(MTGJSON_BASE_URL + "/SetList.json.gz", data_dir, "SetList.json.gz"):
        gz_path = data_dir / "SetList.json.gz"
        if extract_gzip(gz_path, data_dir / "SetList.json"):
            logger.info("SetList.json extracted successfully")
    
    logger.info("MTGJSON data download and extraction complete!")


if __name__ == "__main__":
    asyncio.run(download_all())
