# app/modules/cms/routes/api/store_media.py
"""
Store media and file management endpoints.

Store Context: Uses token_store_id from JWT token (authenticated store API pattern).
The get_current_store_api dependency guarantees token_store_id is present.
"""

import logging

from fastapi import APIRouter, Depends, File, Query, UploadFile
from sqlalchemy.orm import Session

from app.api.deps import get_current_store_api
from app.core.database import get_db
from app.modules.cms.exceptions import MediaOptimizationException
from app.modules.cms.schemas.media import (
    FailedFileInfo,
    MediaDetailResponse,
    MediaItemResponse,
    MediaListResponse,
    MediaMetadataUpdate,
    MediaUploadResponse,
    MediaUsageResponse,
    MultipleUploadResponse,
    OptimizationResultResponse,
    UploadedFileInfo,
)
from app.modules.cms.services.media_service import media_service
from app.modules.tenancy.schemas.auth import UserContext

store_media_router = APIRouter(prefix="/media")
logger = logging.getLogger(__name__)


@store_media_router.get("", response_model=MediaListResponse)
def get_media_library(
    skip: int = Query(0, ge=0),
    limit: int = Query(100, ge=1, le=1000),
    media_type: str | None = Query(None, description="image, video, document"),
    folder: str | None = Query(None, description="Filter by folder"),
    search: str | None = Query(None),
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Get store media library.

    - Get all media files for store
    - Filter by type (image, video, document)
    - Filter by folder
    - Search by filename
    - Support pagination
    """
    media_files, total = media_service.get_media_library(
        db=db,
        store_id=current_user.token_store_id,
        skip=skip,
        limit=limit,
        media_type=media_type,
        folder=folder,
        search=search,
    )

    return MediaListResponse(
        media=[MediaItemResponse.model_validate(m) for m in media_files],
        total=total,
        skip=skip,
        limit=limit,
    )


@store_media_router.post("/upload", response_model=MediaUploadResponse)
async def upload_media(
    file: UploadFile = File(...),
    folder: str | None = Query("general", description="products, general, etc."),
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Upload media file.

    - Accept file upload
    - Validate file type and size
    - Store file in store-specific directory
    - Generate thumbnails for images
    - Save metadata to database
    - Return file URL
    """
    # Read file content
    file_content = await file.read()

    # Upload using service (exceptions will propagate to handler)
    media_file = await media_service.upload_file(
        db=db,
        store_id=current_user.token_store_id,
        file_content=file_content,
        filename=file.filename or "unnamed",
        folder=folder or "general",
    )

    db.commit()

    return MediaUploadResponse(
        id=media_file.id,
        file_url=media_file.file_url,
        thumbnail_url=media_file.thumbnail_url,
        filename=media_file.original_filename,
        file_size=media_file.file_size,
        media_type=media_file.media_type,
        message="File uploaded successfully",
    )


@store_media_router.post("/upload/multiple", response_model=MultipleUploadResponse)
async def upload_multiple_media(
    files: list[UploadFile] = File(...),
    folder: str | None = Query("general"),
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Upload multiple media files at once.

    - Accept multiple files
    - Process each file
    - Return list of uploaded file URLs
    - Handle errors gracefully
    """
    uploaded = []
    failed = []

    for file in files:
        try:
            file_content = await file.read()

            media_file = await media_service.upload_file(
                db=db,
                store_id=current_user.token_store_id,
                file_content=file_content,
                filename=file.filename or "unnamed",
                folder=folder or "general",
            )

            uploaded.append(UploadedFileInfo(
                id=media_file.id,
                filename=media_file.original_filename or media_file.filename,
                file_url=media_file.file_url,
                thumbnail_url=media_file.thumbnail_url,
            ))

        except Exception as e:
            logger.warning(f"Failed to upload {file.filename}: {e}")
            failed.append(FailedFileInfo(
                filename=file.filename or "unnamed",
                error=str(e),
            ))

    db.commit()

    return MultipleUploadResponse(
        uploaded_files=uploaded,
        failed_files=failed,
        total_uploaded=len(uploaded),
        total_failed=len(failed),
        message=f"Uploaded {len(uploaded)} files, {len(failed)} failed",
    )


@store_media_router.get("/{media_id}", response_model=MediaDetailResponse)
def get_media_details(
    media_id: int,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Get media file details.

    - Get file metadata
    - Return file URL
    - Return basic info
    """
    # Service will raise MediaNotFoundException if not found
    media = media_service.get_media(
        db=db,
        store_id=current_user.token_store_id,
        media_id=media_id,
    )

    return MediaDetailResponse.model_validate(media)


@store_media_router.put("/{media_id}", response_model=MediaDetailResponse)
def update_media_metadata(
    media_id: int,
    metadata: MediaMetadataUpdate,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Update media file metadata.

    - Update filename
    - Update alt text
    - Update description
    - Move to different folder
    """
    # Service will raise MediaNotFoundException if not found
    media = media_service.update_media_metadata(
        db=db,
        store_id=current_user.token_store_id,
        media_id=media_id,
        filename=metadata.filename,
        alt_text=metadata.alt_text,
        description=metadata.description,
        folder=metadata.folder,
        metadata=metadata.metadata,
    )

    db.commit()

    return MediaDetailResponse.model_validate(media)


@store_media_router.delete("/{media_id}", response_model=MediaDetailResponse)
def delete_media(
    media_id: int,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Delete media file.

    - Verify file belongs to store
    - Delete file from storage
    - Delete database record
    - Return success/error
    """
    # Service will raise MediaNotFoundException if not found
    media_service.delete_media(
        db=db,
        store_id=current_user.token_store_id,
        media_id=media_id,
    )

    db.commit()

    return MediaDetailResponse(message="Media file deleted successfully")


@store_media_router.get("/{media_id}/usage", response_model=MediaUsageResponse)
def get_media_usage(
    media_id: int,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Get where this media file is being used.

    Discovers usage from all registered module providers.
    """
    # Verify media belongs to store (raises MediaNotFoundException if not found)
    media_service.get_media(
        db=db,
        store_id=current_user.token_store_id,
        media_id=media_id,
    )

    # Discover usage from registered providers
    from app.modules.registry import MODULES

    usage = []
    for module in MODULES.values():
        provider = module.get_media_usage_provider_instance()
        if provider:
            usage.extend(provider.get_media_usage(db, media_id))

    return MediaUsageResponse(
        media_id=media_id,
        usage=usage,
        total_usage_count=len(usage),
    )


@store_media_router.post("/optimize/{media_id}", response_model=OptimizationResultResponse)
def optimize_media(
    media_id: int,
    current_user: UserContext = Depends(get_current_store_api),
    db: Session = Depends(get_db),
):
    """
    Optimize media file (compress, resize, etc.).

    Note: Image optimization requires PIL/Pillow to be installed.
    """
    # Service will raise MediaNotFoundException if not found
    media = media_service.get_media(
        db=db,
        store_id=current_user.token_store_id,
        media_id=media_id,
    )

    if media.media_type != "image":
        raise MediaOptimizationException("Only images can be optimized")

    # For now, return current state - optimization is done on upload
    return OptimizationResultResponse(
        media_id=media_id,
        original_size=media.file_size,
        optimized_size=media.optimized_size or media.file_size,
        savings_percent=0.0 if not media.optimized_size else
            round((1 - media.optimized_size / media.file_size) * 100, 1),
        optimized_url=media.file_url,
        message="Image optimization applied on upload" if media.is_optimized
            else "Image not yet optimized",
    )
