from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form
from sqlalchemy.orm import Session
from typing import List, Optional
import os
import uuid
from pathlib import Path
from PIL import Image
import magic
from config.database import get_db
from config.settings import settings
from models.album import Album, Media, MediaType, MediaLike
from models.user import User
from schemas.album import AlbumCreate, AlbumUpdate, AlbumResponse
from utils.security import get_current_active_user
from utils.settings_service import SettingsService

router = APIRouter()

@router.post("/", response_model=AlbumResponse)
async def create_album(
    album_data: AlbumCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Create a new album."""
    album = Album(
        **album_data.dict(),
        creator_id=current_user.id
    )
    db.add(album)
    db.commit()
    db.refresh(album)
    return format_album_response(album, db, current_user.id)

@router.get("/", response_model=List[AlbumResponse])
async def get_albums(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    event_id: Optional[int] = None
):
    """Get all albums, optionally filtered by event."""
    query = db.query(Album)
    if event_id:
        query = query.filter(Album.event_id == event_id)
    albums = query.order_by(Album.created_at.desc()).all()
    return [format_album_response(album, db, current_user.id) for album in albums]

@router.get("/{album_id}", response_model=AlbumResponse)
async def get_album(
    album_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Get a specific album."""
    album = db.query(Album).filter(Album.id == album_id).first()
    if not album:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Album not found"
        )
    return format_album_response(album, db, current_user.id)

@router.put("/{album_id}", response_model=AlbumResponse)
async def update_album(
    album_id: int,
    album_update: AlbumUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Update an album."""
    album = db.query(Album).filter(Album.id == album_id).first()
    if not album:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Album not found"
        )
    
    if album.creator_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to update this album"
        )
    
    for field, value in album_update.dict(exclude_unset=True).items():
        setattr(album, field, value)
    
    db.commit()
    db.refresh(album)
    return format_album_response(album, db, current_user.id)

@router.delete("/{album_id}")
async def delete_album(
    album_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Delete an album."""
    album = db.query(Album).filter(Album.id == album_id).first()
    if not album:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Album not found"
        )
    
    if album.creator_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to delete this album"
        )
    
    # Delete media files
    for media in album.media:
        try:
            if media.file_path:
                os.remove(settings.UPLOAD_PATH + media.file_path)
            if media.thumbnail_path:
                os.remove(settings.UPLOAD_PATH + media.thumbnail_path)
        except:
            pass
    
    db.delete(album)
    db.commit()
    return {"message": "Album deleted successfully"}

@router.post("/{album_id}/media")
async def upload_media(
    album_id: int,
    files: List[UploadFile] = File(...),
    captions: Optional[List[str]] = Form(None),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Upload media files to an album."""
    album = db.query(Album).filter(Album.id == album_id).first()
    if not album:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Album not found"
        )
    
    if album.creator_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to add media to this album"
        )
    
    # Check max media per album limit
    from utils.settings_service import SettingsService
    max_media_per_album = SettingsService.get_setting(db, "max_media_per_album", 50)
    current_media_count = len(album.media)
    
    if current_media_count + len(files) > max_media_per_album:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Album would exceed maximum of {max_media_per_album} media files. Current: {current_media_count}, trying to add: {len(files)}"
        )
    
    # Create album directory
    album_dir = Path(settings.UPLOAD_PATH) / "albums" / str(album_id)
    album_dir.mkdir(parents=True, exist_ok=True)
    thumbnails_dir = album_dir / "thumbnails"
    thumbnails_dir.mkdir(exist_ok=True)
    
    uploaded_media = []
    
    for i, file in enumerate(files):
        # Check file size
        contents = await file.read()
        file_size = len(contents)
        
        # Get dynamic upload limits
        max_size = SettingsService.get_max_upload_size(db, file.content_type or "unknown")
        if file_size > max_size:
            max_size_mb = max_size // (1024 * 1024)
            raise HTTPException(
                status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
                detail=f"File {file.filename} exceeds maximum size of {max_size_mb}MB"
            )
        
        # Check file type
        mime = magic.from_buffer(contents, mime=True)
        if not SettingsService.is_file_type_allowed(db, mime):
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"File {file.filename} has unsupported type: {mime}"
            )
        
        # Determine media type
        if mime.startswith('image/'):
            media_type = MediaType.IMAGE
        elif mime.startswith('video/'):
            media_type = MediaType.VIDEO
        else:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail=f"File {file.filename} has unsupported type: {mime}"
            )
        
        # Generate unique filename
        file_extension = file.filename.split(".")[-1]
        filename = f"{uuid.uuid4()}.{file_extension}"
        file_path = album_dir / filename
        
        # Save file
        with open(file_path, "wb") as f:
            f.write(contents)
        
        # Process media
        thumbnail_path = None
        width = height = duration = None
        
        if media_type == MediaType.IMAGE:
            # Get image dimensions and create thumbnail
            try:
                img = Image.open(file_path)
                width, height = img.size
                
                # Create thumbnail with better quality
                thumbnail = img.copy()
                thumbnail.thumbnail((800, 800))  # Larger thumbnail for better quality
                thumbnail_filename = f"thumb_{filename}"
                thumbnail_path_full = thumbnails_dir / thumbnail_filename
                thumbnail.save(thumbnail_path_full, quality=95, optimize=True)  # High quality
                thumbnail_path = f"/albums/{album_id}/thumbnails/{thumbnail_filename}"
            except Exception as e:
                print(f"Error processing image: {e}")
        
        # Create media record
        media = Media(
            album_id=album_id,
            file_path=f"/albums/{album_id}/{filename}",
            thumbnail_path=thumbnail_path,
            media_type=media_type,
            caption=captions[i] if captions and i < len(captions) else None,
            file_size=file_size,
            width=width,
            height=height,
            duration=duration
        )
        db.add(media)
        uploaded_media.append(media)
    
    # Set first image as album cover if not set
    if not album.cover_image and uploaded_media:
        first_image = next((m for m in uploaded_media if m.media_type == MediaType.IMAGE), None)
        if first_image:
            album.cover_image = first_image.thumbnail_path or first_image.file_path
    
    db.commit()
    
    # Update event cover image if this album is linked to an event
    if album.event_id:
        update_event_cover_from_album(album.event_id, db)
    
    return {
        "message": f"Successfully uploaded {len(uploaded_media)} files",
        "media_count": len(uploaded_media)
    }

@router.delete("/{album_id}/media/{media_id}")
async def delete_media(
    album_id: int,
    media_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Delete a media file from an album."""
    media = db.query(Media).filter(
        Media.id == media_id,
        Media.album_id == album_id
    ).first()
    
    if not media:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Media not found"
        )
    
    album = media.album
    if album.creator_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to delete this media"
        )
    
    # Delete files
    try:
        if media.file_path:
            os.remove(settings.UPLOAD_PATH + media.file_path)
        if media.thumbnail_path:
            os.remove(settings.UPLOAD_PATH + media.thumbnail_path)
    except:
        pass
    
    db.delete(media)
    db.commit()
    
    # Update event cover image if this album is linked to an event
    if album.event_id:
        update_event_cover_from_album(album.event_id, db)
    
    return {"message": "Media deleted successfully"}

@router.post("/{album_id}/media/{media_id}/like")
async def toggle_media_like(
    album_id: int,
    media_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Toggle like on a media file."""
    media = db.query(Media).filter(
        Media.id == media_id,
        Media.album_id == album_id
    ).first()
    
    if not media:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Media not found"
        )
    
    existing_like = db.query(MediaLike).filter(
        MediaLike.media_id == media_id,
        MediaLike.user_id == current_user.id
    ).first()
    
    if existing_like:
        # Unlike
        db.delete(existing_like)
        media.likes_count = max(0, media.likes_count - 1)
        message = "Like removed"
    else:
        # Like
        like = MediaLike(media_id=media_id, user_id=current_user.id)
        db.add(like)
        media.likes_count += 1
        message = "Media liked"
    
    db.commit()
    
    # Update event cover image if this album is linked to an event
    album = media.album
    if album.event_id:
        update_event_cover_from_album(album.event_id, db)
    
    return {"message": message, "likes_count": media.likes_count}

def format_album_response(album: Album, db: Session, current_user_id: int) -> dict:
    """Format album response with additional information."""
    # Get top media (most liked)
    top_media = db.query(Media).filter(
        Media.album_id == album.id
    ).order_by(Media.likes_count.desc()).limit(3).all()
    
    # Format media with likes information
    formatted_media = []
    for media in album.media:
        # Check if current user liked this media
        is_liked = db.query(MediaLike).filter(
            MediaLike.media_id == media.id,
            MediaLike.user_id == current_user_id
        ).first() is not None
        
        # Format likes
        likes = []
        for like in media.likes:
            user = db.query(User).filter(User.id == like.user_id).first()
            if user:
                likes.append({
                    "id": like.id,
                    "user_id": user.id,
                    "username": user.username,
                    "full_name": user.full_name,
                    "avatar_url": user.avatar_url,
                    "created_at": like.created_at
                })
        
        formatted_media.append({
            "id": media.id,
            "file_path": media.file_path,
            "thumbnail_path": media.thumbnail_path,
            "media_type": media.media_type,
            "caption": media.caption,
            "file_size": media.file_size,
            "width": media.width,
            "height": media.height,
            "duration": media.duration,
            "likes_count": media.likes_count,
            "is_liked": is_liked,
            "likes": likes,
            "created_at": media.created_at
        })
    
    # Format top media
    formatted_top_media = []
    for media in top_media:
        is_liked = db.query(MediaLike).filter(
            MediaLike.media_id == media.id,
            MediaLike.user_id == current_user_id
        ).first() is not None
        
        likes = []
        for like in media.likes:
            user = db.query(User).filter(User.id == like.user_id).first()
            if user:
                likes.append({
                    "id": like.id,
                    "user_id": user.id,
                    "username": user.username,
                    "full_name": user.full_name,
                    "avatar_url": user.avatar_url,
                    "created_at": like.created_at
                })
        
        formatted_top_media.append({
            "id": media.id,
            "file_path": media.file_path,
            "thumbnail_path": media.thumbnail_path,
            "media_type": media.media_type,
            "caption": media.caption,
            "file_size": media.file_size,
            "width": media.width,
            "height": media.height,
            "duration": media.duration,
            "likes_count": media.likes_count,
            "is_liked": is_liked,
            "likes": likes,
            "created_at": media.created_at
        })
    
    return {
        "id": album.id,
        "title": album.title,
        "description": album.description,
        "creator_id": album.creator_id,
        "event_id": album.event_id,
        "cover_image": album.cover_image,
        "created_at": album.created_at,
        "updated_at": album.updated_at,
        "creator_name": album.creator.full_name,
        "media_count": len(album.media),
        "media": formatted_media,
        "top_media": formatted_top_media,
        "event_title": album.event.title if album.event else None
    }

def update_event_cover_from_album(event_id: int, db: Session):
    """Update event cover image from the most liked media in linked albums."""
    from models.event import Event
    
    event = db.query(Event).filter(Event.id == event_id).first()
    if not event:
        return
    
    # Get the most liked media from all albums linked to this event
    most_liked_media = db.query(Media).join(Album).filter(
        Album.event_id == event_id,
        Media.media_type == MediaType.IMAGE
    ).order_by(Media.likes_count.desc()).first()
    
    if most_liked_media:
        event.cover_image = most_liked_media.thumbnail_path or most_liked_media.file_path
        db.commit()
