"""API endpoints for web services."""

from __future__ import annotations

import logging
import threading
from pathlib import Path
from urllib.parse import quote_plus

from fastapi import APIRouter, Query
from fastapi.responses import FileResponse, JSONResponse, RedirectResponse

from code.file_setup.image_cache import ImageCache

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api")

# Global image cache instance
_image_cache = ImageCache()


@router.get("/images/status")
async def get_download_status():
    """
    Get current image download status.
    
    Returns:
        JSON response with download status
    """
    import json
    
    status_file = Path("card_files/images/.download_status.json")
    last_result_file = Path("card_files/images/.last_download_result.json")
    
    if not status_file.exists():
        # No active download - return cache stats plus last download result if available
        stats = _image_cache.cache_statistics()
        last_download = None
        if last_result_file.exists():
            try:
                with last_result_file.open('r', encoding='utf-8') as f:
                    last_download = json.load(f)
            except Exception:
                pass
        return JSONResponse({
            "running": False,
            "last_download": last_download,
            "stats": stats
        })
    
    try:
        with status_file.open('r', encoding='utf-8') as f:
            status = json.load(f)
        
        # If download is complete (or errored), persist result, clean up status file
        if not status.get("running", False):
            try:
                with last_result_file.open('w', encoding='utf-8') as f:
                    json.dump(status, f)
            except Exception:
                pass
            try:
                status_file.unlink()
            except Exception:
                pass
            cache_stats = _image_cache.cache_statistics()
            return JSONResponse({
                "running": False,
                "last_download": status,
                "stats": cache_stats
            })
        
        return JSONResponse(status)
    except Exception as e:
        logger.warning(f"Could not read status file: {e}")
        return JSONResponse({
            "running": False,
            "error": str(e)
        })


@router.get("/images/debug")
async def get_image_debug():
    """
    Debug endpoint to check image cache configuration.
    
    Returns:
        JSON with debug information
    """
    import os
    from pathlib import Path
    
    base_dir = Path(_image_cache.base_dir)
    
    debug_info = {
        "cache_enabled": _image_cache.is_enabled(),
        "env_var": os.getenv("CACHE_CARD_IMAGES", "not set"),
        "base_dir": str(base_dir),
        "base_dir_exists": base_dir.exists(),
        "small_dir": str(base_dir / "small"),
        "small_dir_exists": (base_dir / "small").exists(),
        "normal_dir": str(base_dir / "normal"),
        "normal_dir_exists": (base_dir / "normal").exists(),
    }
    
    # Count files if directories exist
    if (base_dir / "small").exists():
        debug_info["small_count"] = len(list((base_dir / "small").glob("*.jpg")))
    if (base_dir / "normal").exists():
        debug_info["normal_count"] = len(list((base_dir / "normal").glob("*.jpg")))
    
    # Test with a sample card name
    test_card = "Lightning Bolt"
    debug_info["test_card"] = test_card
    test_path_small = _image_cache.get_image_path(test_card, "small")
    test_path_normal = _image_cache.get_image_path(test_card, "normal")
    debug_info["test_path_small"] = str(test_path_small) if test_path_small else None
    debug_info["test_path_normal"] = str(test_path_normal) if test_path_normal else None
    debug_info["test_exists_small"] = test_path_small.exists() if test_path_small else False
    debug_info["test_exists_normal"] = test_path_normal.exists() if test_path_normal else False
    
    return JSONResponse(debug_info)


@router.get("/images/{size}/{card_name}")
async def get_card_image(size: str, card_name: str, face: str = Query(default="front")):
    """
    Serve card image from cache or redirect to Scryfall API.
    
    Args:
        size: Image size ('small' or 'normal')
        card_name: Name of the card
        face: Which face to show ('front' or 'back') for DFC cards
        
    Returns:
        FileResponse if cached locally, RedirectResponse to Scryfall API otherwise
    """
    # Validate size parameter
    if size not in ["small", "normal"]:
        size = "normal"
    
    # Check if caching is enabled
    cache_enabled = _image_cache.is_enabled()
    
    # Check if image exists in cache
    if cache_enabled:
        image_path = None
        
        # For DFC cards, handle front/back faces differently
        if " // " in card_name:
            if face == "back":
                # For back face, ONLY try the back face name
                back_face = card_name.split(" // ")[1].strip()
                logger.debug(f"DFC back face requested: {back_face}")
                image_path = _image_cache.get_image_path(back_face, size)
            else:
                # For front face (or unspecified), try front face name
                front_face = card_name.split(" // ")[0].strip()
                logger.debug(f"DFC front face requested: {front_face}")
                image_path = _image_cache.get_image_path(front_face, size)
        else:
            # Single-faced card, try exact name
            image_path = _image_cache.get_image_path(card_name, size)
        
        if image_path and image_path.exists():
            logger.debug(f"Serving cached image: {card_name} ({size}, {face})")
            return FileResponse(
                image_path,
                media_type="image/jpeg",
                headers={
                    "Cache-Control": "public, max-age=31536000",  # 1 year
                }
            )
        else:
            logger.debug(f"No cached image found for: {card_name} (face: {face})")
    
    # Fallback to Scryfall API
    # For back face requests of DFC cards, we need the full card name
    scryfall_card_name = card_name
    scryfall_params = f"fuzzy={quote_plus(scryfall_card_name)}&format=image&version={size}"
    
    # If this is a back face request, try to find the full DFC name
    if face == "back":
        try:
            from code.services.all_cards_loader import AllCardsLoader
            loader = AllCardsLoader()
            df = loader.load()
            
            # Look for cards where this face name appears in the card_faces
            # The card name format is "Front // Back"
            matching = df[df['name'].str.contains(card_name, case=False, na=False, regex=False)]
            if not matching.empty:
                # Find DFC cards (containing ' // ')
                dfc_matches = matching[matching['name'].str.contains(' // ', na=False, regex=False)]
                if not dfc_matches.empty:
                    # Use the first matching DFC card's full name
                    full_name = dfc_matches.iloc[0]['name']
                    scryfall_card_name = full_name
                    # Add face parameter to Scryfall request
                    scryfall_params = f"exact={quote_plus(full_name)}&format=image&version={size}&face=back"
        except Exception as e:
            logger.warning(f"Could not lookup full card name for back face '{card_name}': {e}")
    
    scryfall_url = f"https://api.scryfall.com/cards/named?{scryfall_params}"
    return RedirectResponse(scryfall_url)


@router.post("/images/download")
async def download_images():
    """
    Start downloading card images in background.
    
    Returns:
        JSON response with status
    """
    if not _image_cache.is_enabled():
        return JSONResponse({
            "ok": False,
            "message": "Image caching is disabled. Set CACHE_CARD_IMAGES=1 to enable."
        }, status_code=400)
    
    # Write initial status
    try:
        status_dir = Path("card_files/images")
        status_dir.mkdir(parents=True, exist_ok=True)
        status_file = status_dir / ".download_status.json"
        
        import json
        with status_file.open('w', encoding='utf-8') as f:
            json.dump({
                "running": True,
                "phase": "bulk_data",
                "message": "Downloading Scryfall bulk data...",
                "current": 0,
                "total": 0,
                "percentage": 0
            }, f)
    except Exception as e:
        logger.warning(f"Could not write initial status: {e}")
    
    # Start download in background thread
    def _download_task():
        import json
        status_file = Path("card_files/images/.download_status.json")
        
        try:
            # Download bulk data first
            logger.info("[IMAGE DOWNLOAD] Starting bulk data download...")
            
            def bulk_progress(downloaded: int, total: int):
                """Progress callback for bulk data download."""
                try:
                    percentage = int(downloaded / total * 100) if total > 0 else 0
                    with status_file.open('w', encoding='utf-8') as f:
                        json.dump({
                            "running": True,
                            "phase": "bulk_data",
                            "message": f"Downloading bulk data: {percentage}%",
                            "current": downloaded,
                            "total": total,
                            "percentage": percentage
                        }, f)
                except Exception as e:
                    logger.warning(f"Could not update bulk progress: {e}")
            
            _image_cache.download_bulk_data(progress_callback=bulk_progress)
            
            # Download images
            logger.info("[IMAGE DOWNLOAD] Starting image downloads...")
            
            def image_progress(current: int, total: int, card_name: str):
                """Progress callback for image downloads."""
                try:
                    percentage = int(current / total * 100) if total > 0 else 0
                    with status_file.open('w', encoding='utf-8') as f:
                        json.dump({
                            "running": True,
                            "phase": "images",
                            "message": f"Downloading images: {card_name}",
                            "current": current,
                            "total": total,
                            "percentage": percentage
                        }, f)
                    
                    # Log progress every 100 cards
                    if current % 100 == 0:
                        logger.info(f"[IMAGE DOWNLOAD] Progress: {current}/{total} ({percentage}%)")
                        
                except Exception as e:
                    logger.warning(f"Could not update image progress: {e}")
            
            stats = _image_cache.download_images(progress_callback=image_progress)
            
            # Write completion status
            with status_file.open('w', encoding='utf-8') as f:
                json.dump({
                    "running": False,
                    "phase": "complete",
                    "message": f"Download complete: {stats.get('downloaded', 0)} new images",
                    "stats": stats,
                    "percentage": 100
                }, f)
            
            logger.info(f"[IMAGE DOWNLOAD] Complete: {stats}")
            
        except Exception as e:
            logger.error(f"[IMAGE DOWNLOAD] Failed: {e}", exc_info=True)
            try:
                with status_file.open('w', encoding='utf-8') as f:
                    json.dump({
                        "running": False,
                        "phase": "error",
                        "message": f"Download failed: {str(e)}",
                        "percentage": 0
                    }, f)
            except Exception:
                pass
    
    # Start background thread
    thread = threading.Thread(target=_download_task, daemon=True)
    thread.start()
    
    return JSONResponse({
        "ok": True,
        "message": "Image download started in background"
    }, status_code=202)
