import os
import shutil
from celery.result import AsyncResult
 
from typing import List, Optional 
from fastapi.responses import JSONResponse
from fastapi import APIRouter, UploadFile, File, Depends, Form

from app.tasks import analyse
from app.schemas import VideoBase, Prediction, Task
from app.utils import generate_unique_filename, get_file_duration, extract_title_and_duration

router = APIRouter(prefix="/tasks", tags=["Based Content Tasks"])
extentions = (".mp4", ".mkv", ".avi", ".mov", ".ts")

@router.post("/process")
async def process(
    file: Optional[UploadFile] = File(default=None),
    url: Optional[str] = Form(None),
    confidence: Optional[float] = Form(None),
    categories: Optional[List[str]] = Form(None)
):
    """
    Process the data from the request.

    Parameters:
        - request: ProcessDataRequest object containing the request data.
            - file (optional): The form content file (bytes).
            - url (optional): The URL (HTTP/HTTPS).
            - confidence (optional): The confidence value (float).
            - categories (optional): The list of categories (List[str]).

    Returns:
        A dict with the message "Data processed successfully".
    """ 
    try:
        if not file and not url:
            return JSONResponse(
                {
                    "message": "Either 'file' or 'url' must be provided.", 
                    "status": "ERROR"
                },
                status_code=400
            )
        
        title, duration, source = None, None, None

        if file  and file.filename and not url :
            if (file.filename).endswith(extentions):
                # Generate unique filename
                title, extension = os.path.splitext(file.filename)
                unique_filename = generate_unique_filename(extension)

                # Saving the file
                file_path = os.path.join("static", unique_filename)
                with open(file_path, "wb") as f:
                    shutil.copyfileobj(file.file, f)

                # Get file source & duration
                source = file_path
                duration = get_file_duration(file_path)
                message = "File detected and processed successfully"
            else:
                # Invalid file type
                return JSONResponse(
                    { 
                        "message": "Invalid file type. Only video files (.mp4, .avi, .mov) and .ts files are supported.", 
                        "status": "ERROR"
                    },
                    status_code=400
                )
        elif url and not file: 
            # Check if the URL is for a video file
            if url.endswith(extentions):
                # Perform video file processing logic
                message = "Video/TS file URL detected and processed successfully" 
                source = url
                title, duration = extract_title_and_duration(url)
                title, _ = os.path.splitext(title)
            else:
                # Invalid file type
                return JSONResponse(
                    { 
                        "message": "Invalid file type. Only video files (.mp4, .avi, .mov) and .ts files are supported.",
                        "status": "ERROR"
                    },
                    status_code=400
                )
        else:
            # Neither file nor URL provided
            return JSONResponse(
                { 
                    "message": "Either a file or a URL must be provided.",
                    "status": "ERROR"
                },
                status_code=400
            )
        #    
        try: 
            # Create VideoBase response model instance
            video_data = {
                "title":title,
                "duration":duration,
                "source":source,
                "confidence":confidence,
                "categories":categories 
            } 
            # Run Celery Task For Object Detection Using AWS Rekognition
            task_id = analyse.delay(video_data)
            return JSONResponse(
                {
                    "task_id": str(task_id),
                    "message": message, 
                    "url_result": f"/api/v1/tasks/result/{task_id}",
                    "status": "PROCESSING"
                },
                status_code=202
            )
        except Exception as ex: 
            return JSONResponse(
                {
                    "task_id": str(task_id),
                    "message": ex, 
                    "status": 400
                },
                status_code=400
            )
    except Exception as ex: 
        return JSONResponse(
            {
                "data": None,
                "message": ex, 
                "status": 400
            },
            status_code=400
        )

@router.get("/status/{task_id}", response_model=Task)
async def status(task_id: str): 
    task = AsyncResult(task_id)
    return JSONResponse(
        {
            "task_id": str(task_id), 
            "status": task.status, 
            "result": ""
        }, 
        status_code=200
    )
 
@router.get("/result/{task_id}", response_model=Prediction)
async def result(task_id: str):
    task = AsyncResult(task_id) 
    # Task Not Ready
    if not task.ready():
        return JSONResponse(
            {
                "task_id": str(task_id), 
                "status": task.status, 
                "result": ""
            },
            status_code=202)

    # Task done: return the value
    task_result = task.get()
    result = task_result.get("result")
    return JSONResponse(
        {
            "task_id": str(task_id), 
            "status": task_result.get("status"), 
            "result": result
        },
        status_code=200
    )

