from fastapi import APIRouter, Depends, HTTPException, status, UploadFile, File, Form
from sqlalchemy.orm import Session
from typing import List
import os
import uuid
from pathlib import Path
from config.database import get_db
from config.settings import settings
from models.vlog import Vlog, VlogLike, VlogComment, VlogView
from models.user import User
from models.notification import Notification, NotificationType
from schemas.vlog import VlogCreate, VlogUpdate, VlogResponse, VlogCommentCreate
from utils.security import get_current_active_user
from utils.video_utils import generate_video_thumbnail, get_video_duration
from utils.settings_service import SettingsService

router = APIRouter()

@router.post("/", response_model=VlogResponse)
async def create_vlog(
    vlog_data: VlogCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Create a new vlog."""
    vlog = Vlog(
        author_id=current_user.id,
        **vlog_data.dict()
    )
    db.add(vlog)
    db.commit()
    db.refresh(vlog)
    return format_vlog_response(vlog, db, current_user.id)

@router.get("/", response_model=List[VlogResponse])
async def get_vlogs(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
    limit: int = 20,
    offset: int = 0
):
    """Get all vlogs."""
    vlogs = db.query(Vlog).order_by(Vlog.created_at.desc()).limit(limit).offset(offset).all()
    return [format_vlog_response(vlog, db, current_user.id) for vlog in vlogs]

@router.get("/{vlog_id}", response_model=VlogResponse)
async def get_vlog(
    vlog_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Get a specific vlog."""
    vlog = db.query(Vlog).filter(Vlog.id == vlog_id).first()
    if not vlog:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Vlog not found"
        )
    
    # Manage views and replays
    view = db.query(VlogView).filter(
        VlogView.vlog_id == vlog_id,
        VlogView.user_id == current_user.id
    ).first()
    
    if view:
        # User has already viewed this vlog -> Count as replay
        vlog.replays_count = (vlog.replays_count or 0) + 1
    else:
        # First time viewing -> Count as unique view
        new_view = VlogView(vlog_id=vlog_id, user_id=current_user.id)
        db.add(new_view)
        vlog.views_count += 1
    
    db.commit()
    
    return format_vlog_response(vlog, db, current_user.id)

@router.put("/{vlog_id}", response_model=VlogResponse)
async def update_vlog(
    vlog_id: int,
    vlog_update: VlogUpdate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Update a vlog."""
    vlog = db.query(Vlog).filter(Vlog.id == vlog_id).first()
    if not vlog:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Vlog not found"
        )
    
    if vlog.author_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to update this vlog"
        )
    
    for field, value in vlog_update.dict(exclude_unset=True).items():
        setattr(vlog, field, value)
    
    db.commit()
    db.refresh(vlog)
    return format_vlog_response(vlog, db, current_user.id)

@router.delete("/{vlog_id}")
async def delete_vlog(
    vlog_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Delete a vlog."""
    vlog = db.query(Vlog).filter(Vlog.id == vlog_id).first()
    if not vlog:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Vlog not found"
        )
    
    if vlog.author_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to delete this vlog"
        )
    
    # Delete video files
    try:
        if vlog.video_url:
            os.remove(settings.UPLOAD_PATH + vlog.video_url)
        if vlog.thumbnail_url:
            os.remove(settings.UPLOAD_PATH + vlog.thumbnail_url)
    except:
        pass
    
    db.delete(vlog)
    db.commit()
    return {"message": "Vlog deleted successfully"}

@router.post("/{vlog_id}/like")
async def toggle_vlog_like(
    vlog_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Toggle like on a vlog."""
    vlog = db.query(Vlog).filter(Vlog.id == vlog_id).first()
    if not vlog:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Vlog not found"
        )
    
    existing_like = db.query(VlogLike).filter(
        VlogLike.vlog_id == vlog_id,
        VlogLike.user_id == current_user.id
    ).first()
    
    if existing_like:
        # Unlike
        db.delete(existing_like)
        vlog.likes_count = max(0, vlog.likes_count - 1)
        message = "Like removed"
    else:
        # Like
        try:
            like = VlogLike(vlog_id=vlog_id, user_id=current_user.id)
            db.add(like)
            vlog.likes_count += 1
            message = "Vlog liked"
        except Exception:
            # Handle potential race condition or constraint violation
            db.rollback()
            return {"message": "Already liked", "likes_count": vlog.likes_count}
    
    db.commit()
    return {"message": message, "likes_count": vlog.likes_count}

@router.post("/{vlog_id}/comment")
async def add_vlog_comment(
    vlog_id: int,
    comment_data: VlogCommentCreate,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Add a comment to a vlog."""
    vlog = db.query(Vlog).filter(Vlog.id == vlog_id).first()
    if not vlog:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Vlog not found"
        )
    
    comment = VlogComment(
        vlog_id=vlog_id,
        user_id=current_user.id,
        content=comment_data.content
    )
    db.add(comment)
    db.commit()
    db.refresh(comment)
    
    return {
        "message": "Comment added successfully",
        "comment": {
            "id": comment.id,
            "content": comment.content,
            "user_id": comment.user_id,
            "username": current_user.username,
            "full_name": current_user.full_name,
            "avatar_url": current_user.avatar_url,
            "created_at": comment.created_at
        }
    }

@router.delete("/{vlog_id}/comment/{comment_id}")
async def delete_vlog_comment(
    vlog_id: int,
    comment_id: int,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Delete a comment from a vlog."""
    comment = db.query(VlogComment).filter(
        VlogComment.id == comment_id,
        VlogComment.vlog_id == vlog_id
    ).first()
    
    if not comment:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="Comment not found"
        )
    
    if comment.user_id != current_user.id and not current_user.is_admin:
        raise HTTPException(
            status_code=status.HTTP_403_FORBIDDEN,
            detail="Not authorized to delete this comment"
        )
    
    db.delete(comment)
    db.commit()
    return {"message": "Comment deleted successfully"}

@router.post("/upload")
async def upload_vlog_video(
    title: str = Form(...),
    description: str = Form(None),
    video: UploadFile = File(...),
    thumbnail: UploadFile = File(None),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user)
):
    """Upload a vlog video."""
    # Validate video file
    if not SettingsService.is_file_type_allowed(db, video.content_type or "unknown"):
        allowed_types = SettingsService.get_setting(db, "allowed_video_types", 
            ["video/mp4", "video/mpeg", "video/quicktime", "video/webm"])
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"Invalid video type. Allowed types: {', '.join(allowed_types)}"
        )
    
    # Check file size
    video_content = await video.read()
    max_size = SettingsService.get_max_upload_size(db, video.content_type or "video/mp4", is_vlog=True)
    if len(video_content) > max_size:
        max_size_mb = max_size // (1024 * 1024)
        raise HTTPException(
            status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
            detail=f"Video file too large. Maximum size: {max_size_mb}MB"
        )
    
    # Create vlog directory
    vlog_dir = Path(settings.UPLOAD_PATH) / "vlogs" / str(current_user.id)
    vlog_dir.mkdir(parents=True, exist_ok=True)
    
    # Save video
    video_extension = video.filename.split(".")[-1]
    video_filename = f"{uuid.uuid4()}.{video_extension}"
    video_path = vlog_dir / video_filename
    
    with open(video_path, "wb") as f:
        f.write(video_content)
    
    # Process thumbnail
    thumbnail_url = None
    if thumbnail:
        if thumbnail.content_type not in settings.ALLOWED_IMAGE_TYPES:
            raise HTTPException(
                status_code=status.HTTP_400_BAD_REQUEST,
                detail="Invalid thumbnail type"
            )
        
        thumbnail_content = await thumbnail.read()
        thumbnail_extension = thumbnail.filename.split(".")[-1]
        thumbnail_filename = f"thumb_{uuid.uuid4()}.{thumbnail_extension}"
        thumbnail_path = vlog_dir / thumbnail_filename
        
        with open(thumbnail_path, "wb") as f:
            f.write(thumbnail_content)
        
        thumbnail_url = f"/vlogs/{current_user.id}/{thumbnail_filename}"
    else:
        # Generate automatic thumbnail from video
        try:
            thumbnail_filename = f"auto_thumb_{uuid.uuid4()}.jpg"
            thumbnail_path = vlog_dir / thumbnail_filename
            
            if generate_video_thumbnail(str(video_path), str(thumbnail_path)):
                thumbnail_url = f"/vlogs/{current_user.id}/{thumbnail_filename}"
        except Exception as e:
            print(f"Error generating automatic thumbnail: {e}")
            # Continue without thumbnail if generation fails
    
    # Get video duration
    duration = None
    try:
        duration = int(get_video_duration(str(video_path)))
    except Exception as e:
        print(f"Error getting video duration: {e}")
    
    # Create vlog record
    vlog = Vlog(
        author_id=current_user.id,
        title=title,
        description=description,
        video_url=f"/vlogs/{current_user.id}/{video_filename}",
        thumbnail_url=thumbnail_url,
        duration=duration
    )
    db.add(vlog)
    db.commit()
    db.refresh(vlog)
    
    # Create notifications for all active users (except the creator)
    users = db.query(User).filter(User.is_active == True).all()
    for user in users:
        if user.id != current_user.id:
            notification = Notification(
                user_id=user.id,
                type=NotificationType.NEW_VLOG,
                title="Nouveau vlog",
                message=f"{current_user.full_name} a publié un nouveau vlog : {vlog.title}",
                link=f"/vlogs/{vlog.id}",
                is_read=False
            )
            db.add(notification)
    
    db.commit()
    
    return format_vlog_response(vlog, db, current_user.id)

def format_vlog_response(vlog: Vlog, db: Session, current_user_id: int) -> dict:
    """Format vlog response with author information, likes, and comments."""
    # Check if current user liked this vlog
    is_liked = db.query(VlogLike).filter(
        VlogLike.vlog_id == vlog.id,
        VlogLike.user_id == current_user_id
    ).first() is not None
    
    # Format likes
    likes = []
    for like in vlog.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
            })
    
    # Format comments
    comments = []
    for comment in vlog.comments:
        user = db.query(User).filter(User.id == comment.user_id).first()
        if user:
            comments.append({
                "id": comment.id,
                "user_id": user.id,
                "username": user.username,
                "full_name": user.full_name,
                "avatar_url": user.avatar_url,
                "content": comment.content,
                "created_at": comment.created_at,
                "updated_at": comment.updated_at
            })
    
    return {
        "id": vlog.id,
        "author_id": vlog.author_id,
        "title": vlog.title,
        "description": vlog.description,
        "video_url": vlog.video_url,
        "thumbnail_url": vlog.thumbnail_url,
        "duration": vlog.duration,
        "views_count": vlog.views_count,
        "replays_count": vlog.replays_count,
        "likes_count": vlog.likes_count,
        "created_at": vlog.created_at,
        "updated_at": vlog.updated_at,
        "author_name": vlog.author.full_name,
        "author_avatar": vlog.author.avatar_url,
        "is_liked": is_liked,
        "likes": likes,
        "comments": comments
    }
