import logging
from typing import Annotated, Optional

from api.function import data_ingestion
from api.router.user import user_dependency
from api.auth import check_user_authentication, check_admin_authentication

from fastapi import Form, APIRouter, File, UploadFile, Depends
from fastapi.responses import JSONResponse

from db.models import Metadata
from db.database import get_db
from db.query.query_book import BookQuery
from db.query.query_category import CategoryQuery
from db.fetching import DataFetching

from config import MYSQL_CONFIG
from utils.error_handlers import handle_exception
from script.vector_db import IndexManager
from service.dto import MetadataResponse
from service.aws_loader import Loader
from sqlalchemy.orm import Session
from sqlalchemy.future import select


router = APIRouter(tags=["Book"])

index_manager = IndexManager()
db_dependency = Annotated[Session, Depends(get_db)]


@router.get("/book")
async def get_metadata(user: user_dependency, db: db_dependency):
    auth_response = check_user_authentication(user)
    if auth_response:
        print(auth_response)
        return auth_response
    try:
        # Join Metadata with Category to get the category name
        fetching = DataFetching(user, db)
        metadata_fetching = fetching.metadata_fetching()

        # Transform results into MetadataResponse model with optional thumbnail handling
        return metadata_fetching

    except Exception as e:
        return handle_exception(e)


@router.post("/book")
async def upload_file(
    user: user_dependency,
    db: db_dependency,
    title: str = Form(...),
    author: str = Form(...),
    category_id: int = Form(...),
    year: int = Form(...),
    publisher: str = Form(...),
    file: UploadFile = File(...),
    lang: str = Form(None),
    thumbnail: Optional[UploadFile] = File(None),
):
    auth_response = check_admin_authentication(user)
    if auth_response:
        return auth_response
    
    # Restrict `lang` to only "id" or "en"
    lang = lang if lang in {"id", "en"} else "en"

    # Query the category based on category_id
    category_query = CategoryQuery(user)
    category = category_query.get_category(db, category_id)

    try:
        reference = {
            "title": title,
            "author": author,
            "category": category,
            "year": year,
            "publisher": publisher,
        }

        # Process the file and handle data ingestion
        response = await data_ingestion(reference, file, lang)
        
        if isinstance(response, JSONResponse):
            return response  # Return the error response directly
        
        if thumbnail:
            file_name = f"{reference['title']}"
            aws_loader = Loader()
            ekstensi_file = file.filename.split(".")[-1].lower()
            aws_loader.upload_image_to_s3(file=thumbnail, custom_name=f"{file_name}.{ekstensi_file}")
            

        # Create a new Metadata object
        book_query = BookQuery(user)
        book_query.add_book(db, title, author, category_id, year, publisher)
        logging.info("Database Inserted")

        return {
            "filename": file.filename,
            "response": response,
            "info": "upload file successfully",
        }

    except Exception as e:
        return handle_exception(e)


@router.put("/book/{metadata_id}")
async def update_metadata(
    user: user_dependency,
    db: db_dependency,
    metadata_id: int,
    title: str = Form(...),
    author: str = Form(...),
    category_id: int = Form(...),
    year: int = Form(...),
    publisher: str = Form(...),
    thumbnail: Optional[UploadFile] = File(None),
):
    auth_response = check_admin_authentication(user)
    if auth_response:
        return auth_response

    try:
        # fetch current metadata
        book_query = BookQuery(user)
        current_metadata = book_query.get_metadata_books(db, metadata_id)

        # Fetch current and new categories
        category_query = CategoryQuery(user)
        current_category = category_query.get_current_category(db, metadata_id)
        
        new_category = category_query.get_category(db, category_id)


        # Prepare the references
        current_reference = {
            "title": current_metadata.title,
            "author": current_metadata.author,
            "category": current_category,
            "year": current_metadata.year,
            "publisher": current_metadata.publisher,
        }

        new_reference = {
            "title": title,
            "author": author,
            "category": new_category,
            "year": year,
            "publisher": publisher,
        }

        # Update vector database
        index_manager.update_vector_database(current_reference, new_reference)

        # Update existing metadata entry
        metadata = db.query(Metadata).filter(Metadata.id == metadata_id).first()
        print(metadata)

        if not metadata:
            return JSONResponse(status_code=404, content="Metadata not found")

        updated_metadata = book_query.update_metadata_entry(
            db, metadata_id, title, author, category_id, year, publisher
        )
        print(updated_metadata)
        updated_category = category_query.get_category(db, updated_metadata.category_id)
        print(updated_category)

        return MetadataResponse(
            id=metadata_id,
            title=updated_metadata.title,
            author=updated_metadata.author,
            category=updated_category,  # Assuming category relationship is available
            category_id=updated_metadata.category_id,
            year=updated_metadata.year,
            publisher=updated_metadata.publisher,
            thumbnail=(
                updated_metadata.thumbnail
                if updated_metadata.thumbnail is not None
                else None
            ),
        )

    except Exception as e:
        return handle_exception(e)

@router.delete("/book/{metadata_id}")
async def delete_metadata(user: user_dependency, db: db_dependency, metadata_id: int):
    auth_response = check_admin_authentication(user)
    if auth_response:
        return auth_response

    try:
        # Check if metadata exists before deletion
        metadata = db.query(Metadata).filter(Metadata.id == metadata_id).first()

        if not metadata:
            return JSONResponse(status_code=404, content="Metadata not found")

        # Delete from the vector database and the database
        index_manager.delete_vector_database(metadata.title)
        
        db.delete(metadata)
        db.commit()

        return {"Status": "delete successfully"}

    except Exception as e:
        return handle_exception(e)