from typing import Any

from app.auth import AuthenticatedUser, get_current_user
from app.core.storage import OSSStorageService, get_storage_service
from app.dependencies import get_generated_video_repository, get_project_repository
from app.schemas.generated_video import (
    GeneratedVideoDownloadUrlResponse,
    GeneratedVideoResponse,
    ListGeneratedVideosResponse,
    UpdateGeneratedVideoReviewRequest,
)
from fastapi import APIRouter, Depends, HTTPException, Query

from packages.application import (
    GetGeneratedVideoDownloadUrlUseCase,
    GetGeneratedVideoUseCase,
    ListGeneratedVideosUseCase,
)

router = APIRouter()


def _to_generated_video_response(item, download_url: str | None = None) -> GeneratedVideoResponse:
    return GeneratedVideoResponse(
        id=item.id,
        project_id=item.project_id,
        generation_task_id=item.generation_task_id,
        name=item.name,
        file_url=item.file_url,
        file_size=item.file_size,
        duration=item.duration,
        thumbnail_url=item.thumbnail_url,
        width=item.width,
        height=item.height,
        fps=item.fps,
        status=item.status,
        review_status=item.review_status,
        generation_params=item.generation_params,
        download_url=download_url,
    )


@router.get("", response_model=ListGeneratedVideosResponse)
def list_generated_videos(
    project_id: str | None = Query(None),
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    generated_video_repository: Any = Depends(get_generated_video_repository),
    project_repository: Any = Depends(get_project_repository),
    storage_service: OSSStorageService = Depends(get_storage_service),
) -> ListGeneratedVideosResponse:
    user_id = authenticated_user.user.id
    use_case = ListGeneratedVideosUseCase(generated_video_repository)

    if project_id:
        # If project_id provided, check access and filter by project
        project = project_repository.find_by_id(project_id)
        if project is None:
            raise HTTPException(status_code=404, detail=f"Project {project_id} not found")
        items = use_case.execute(project_id)
    else:
        # If no project_id, list all videos from accessible projects
        accessible_projects = project_repository.find_accessible_projects(user_id)
        all_items = []
        for proj in accessible_projects:
            all_items.extend(use_case.execute(proj.id))
        items = all_items

    # Generate download URLs for each video
    responses = []
    for item in items:
        download_url = storage_service.get_download_url(item.file_url)
        responses.append(_to_generated_video_response(item, download_url=download_url))
    return ListGeneratedVideosResponse(items=responses)


@router.get("/{video_id}", response_model=GeneratedVideoResponse)
def get_generated_video(
    video_id: str,
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    generated_video_repository: Any = Depends(get_generated_video_repository),
    storage_service: OSSStorageService = Depends(get_storage_service),
) -> GeneratedVideoResponse:
    use_case = GetGeneratedVideoUseCase(generated_video_repository)
    item = use_case.execute(video_id)
    if item is None:
        raise HTTPException(status_code=404, detail=f"GeneratedVideo {video_id} not found")
    download_url = storage_service.get_download_url(item.file_url)
    return _to_generated_video_response(item, download_url=download_url)


@router.patch("/{video_id}/review", response_model=GeneratedVideoResponse)
def update_generated_video_review_status(
    video_id: str,
    request: UpdateGeneratedVideoReviewRequest,
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    generated_video_repository: Any = Depends(get_generated_video_repository),
    storage_service: OSSStorageService = Depends(get_storage_service),
) -> GeneratedVideoResponse:
    video = generated_video_repository.get(video_id)
    if video is None:
        raise HTTPException(status_code=404, detail=f"GeneratedVideo {video_id} not found")
    video.review_status = request.review_status
    updated = generated_video_repository.update(video)
    download_url = storage_service.get_download_url(updated.file_url)
    return _to_generated_video_response(updated, download_url=download_url)


@router.get("/{video_id}/download-url", response_model=GeneratedVideoDownloadUrlResponse)
def get_generated_video_download_url(
    video_id: str,
    authenticated_user: AuthenticatedUser = Depends(get_current_user),
    generated_video_repository: Any = Depends(get_generated_video_repository),
    storage_service: OSSStorageService = Depends(get_storage_service),
) -> GeneratedVideoDownloadUrlResponse:
    video = generated_video_repository.get(video_id)
    if video is None:
        raise HTTPException(status_code=404, detail=f"GeneratedVideo {video_id} not found")
    use_case = GetGeneratedVideoDownloadUrlUseCase(generated_video_repository)
    file_url = use_case.execute(video_id)
    if file_url is None:
        raise HTTPException(status_code=404, detail=f"GeneratedVideo {video_id} not found")
    download_url = storage_service.get_download_url(file_url)
    return GeneratedVideoDownloadUrlResponse(video_id=video_id, download_url=download_url)
