import json
import logging
from typing import List, Optional

from datetime import datetime, date

from fastapi import APIRouter, Body, Depends, HTTPException, Query
from pydantic import BaseModel
from sqlalchemy.ext.asyncio import AsyncSession

from core.database import get_db
from services.chat_attachments import Chat_attachmentsService

# Set up logging
logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/entities/chat_attachments", tags=["chat_attachments"])


# ---------- Pydantic Schemas ----------
class Chat_attachmentsData(BaseModel):
    """Entity data schema (for create/update)"""
    conversation_id: int
    message_id: int = None
    object_key: str
    file_name: str
    mime_type: str = None
    size_bytes: int = None
    url: str = None


class Chat_attachmentsUpdateData(BaseModel):
    """Update entity data (partial updates allowed)"""
    conversation_id: Optional[int] = None
    message_id: Optional[int] = None
    object_key: Optional[str] = None
    file_name: Optional[str] = None
    mime_type: Optional[str] = None
    size_bytes: Optional[int] = None
    url: Optional[str] = None


class Chat_attachmentsResponse(BaseModel):
    """Entity response schema"""
    id: int
    conversation_id: int
    message_id: Optional[int] = None
    object_key: str
    file_name: str
    mime_type: Optional[str] = None
    size_bytes: Optional[int] = None
    url: Optional[str] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


class Chat_attachmentsListResponse(BaseModel):
    """List response schema"""
    items: List[Chat_attachmentsResponse]
    total: int
    skip: int
    limit: int


class Chat_attachmentsBatchCreateRequest(BaseModel):
    """Batch create request"""
    items: List[Chat_attachmentsData]


class Chat_attachmentsBatchUpdateItem(BaseModel):
    """Batch update item"""
    id: int
    updates: Chat_attachmentsUpdateData


class Chat_attachmentsBatchUpdateRequest(BaseModel):
    """Batch update request"""
    items: List[Chat_attachmentsBatchUpdateItem]


class Chat_attachmentsBatchDeleteRequest(BaseModel):
    """Batch delete request"""
    ids: List[int]


# ---------- Routes ----------
@router.get("", response_model=Chat_attachmentsListResponse)
async def query_chat_attachmentss(
    query: str = Query(None, description="Query conditions (JSON string)"),
    sort: str = Query(None, description="Sort field (prefix with '-' for descending)"),
    skip: int = Query(0, ge=0, description="Number of records to skip"),
    limit: int = Query(20, ge=1, le=2000, description="Max number of records to return"),
    fields: str = Query(None, description="Comma-separated list of fields to return"),
    db: AsyncSession = Depends(get_db),
):
    """Query chat_attachmentss with filtering, sorting, and pagination"""
    logger.debug(f"Querying chat_attachmentss: query={query}, sort={sort}, skip={skip}, limit={limit}, fields={fields}")
    
    service = Chat_attachmentsService(db)
    try:
        # Parse query JSON if provided
        query_dict = None
        if query:
            try:
                query_dict = json.loads(query)
            except json.JSONDecodeError:
                raise HTTPException(status_code=400, detail="Invalid query JSON format")
        
        result = await service.get_list(
            skip=skip, 
            limit=limit,
            query_dict=query_dict,
            sort=sort,
        )
        logger.debug(f"Found {result['total']} chat_attachmentss")
        return result
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error querying chat_attachmentss: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.get("/all", response_model=Chat_attachmentsListResponse)
async def query_chat_attachmentss_all(
    query: str = Query(None, description="Query conditions (JSON string)"),
    sort: str = Query(None, description="Sort field (prefix with '-' for descending)"),
    skip: int = Query(0, ge=0, description="Number of records to skip"),
    limit: int = Query(20, ge=1, le=2000, description="Max number of records to return"),
    fields: str = Query(None, description="Comma-separated list of fields to return"),
    db: AsyncSession = Depends(get_db),
):
    # Query chat_attachmentss with filtering, sorting, and pagination without user limitation
    logger.debug(f"Querying chat_attachmentss: query={query}, sort={sort}, skip={skip}, limit={limit}, fields={fields}")

    service = Chat_attachmentsService(db)
    try:
        # Parse query JSON if provided
        query_dict = None
        if query:
            try:
                query_dict = json.loads(query)
            except json.JSONDecodeError:
                raise HTTPException(status_code=400, detail="Invalid query JSON format")

        result = await service.get_list(
            skip=skip,
            limit=limit,
            query_dict=query_dict,
            sort=sort
        )
        logger.debug(f"Found {result['total']} chat_attachmentss")
        return result
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error querying chat_attachmentss: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.get("/{id}", response_model=Chat_attachmentsResponse)
async def get_chat_attachments(
    id: int,
    fields: str = Query(None, description="Comma-separated list of fields to return"),
    db: AsyncSession = Depends(get_db),
):
    """Get a single chat_attachments by ID"""
    logger.debug(f"Fetching chat_attachments with id: {id}, fields={fields}")
    
    service = Chat_attachmentsService(db)
    try:
        result = await service.get_by_id(id)
        if not result:
            logger.warning(f"Chat_attachments with id {id} not found")
            raise HTTPException(status_code=404, detail="Chat_attachments not found")
        
        return result
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error fetching chat_attachments {id}: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.post("", response_model=Chat_attachmentsResponse, status_code=201)
async def create_chat_attachments(
    data: Chat_attachmentsData,
    db: AsyncSession = Depends(get_db),
):
    """Create a new chat_attachments"""
    logger.debug(f"Creating new chat_attachments with data: {data}")
    
    service = Chat_attachmentsService(db)
    try:
        result = await service.create(data.model_dump())
        if not result:
            raise HTTPException(status_code=400, detail="Failed to create chat_attachments")
        
        logger.info(f"Chat_attachments created successfully with id: {result.id}")
        return result
    except ValueError as e:
        logger.error(f"Validation error creating chat_attachments: {str(e)}")
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Error creating chat_attachments: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.post("/batch", response_model=List[Chat_attachmentsResponse], status_code=201)
async def create_chat_attachmentss_batch(
    request: Chat_attachmentsBatchCreateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Create multiple chat_attachmentss in a single request"""
    logger.debug(f"Batch creating {len(request.items)} chat_attachmentss")
    
    service = Chat_attachmentsService(db)
    results = []
    
    try:
        for item_data in request.items:
            result = await service.create(item_data.model_dump())
            if result:
                results.append(result)
        
        logger.info(f"Batch created {len(results)} chat_attachmentss successfully")
        return results
    except Exception as e:
        await db.rollback()
        logger.error(f"Error in batch create: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Batch create failed: {str(e)}")


@router.put("/batch", response_model=List[Chat_attachmentsResponse])
async def update_chat_attachmentss_batch(
    request: Chat_attachmentsBatchUpdateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Update multiple chat_attachmentss in a single request"""
    logger.debug(f"Batch updating {len(request.items)} chat_attachmentss")
    
    service = Chat_attachmentsService(db)
    results = []
    
    try:
        for item in request.items:
            # Only include non-None values for partial updates
            update_dict = {k: v for k, v in item.updates.model_dump().items() if v is not None}
            result = await service.update(item.id, update_dict)
            if result:
                results.append(result)
        
        logger.info(f"Batch updated {len(results)} chat_attachmentss successfully")
        return results
    except Exception as e:
        await db.rollback()
        logger.error(f"Error in batch update: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Batch update failed: {str(e)}")


@router.put("/{id}", response_model=Chat_attachmentsResponse)
async def update_chat_attachments(
    id: int,
    data: Chat_attachmentsUpdateData,
    db: AsyncSession = Depends(get_db),
):
    """Update an existing chat_attachments"""
    logger.debug(f"Updating chat_attachments {id} with data: {data}")

    service = Chat_attachmentsService(db)
    try:
        # Only include non-None values for partial updates
        update_dict = {k: v for k, v in data.model_dump().items() if v is not None}
        result = await service.update(id, update_dict)
        if not result:
            logger.warning(f"Chat_attachments with id {id} not found for update")
            raise HTTPException(status_code=404, detail="Chat_attachments not found")
        
        logger.info(f"Chat_attachments {id} updated successfully")
        return result
    except HTTPException:
        raise
    except ValueError as e:
        logger.error(f"Validation error updating chat_attachments {id}: {str(e)}")
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Error updating chat_attachments {id}: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.delete("/batch")
async def delete_chat_attachmentss_batch(
    request: Chat_attachmentsBatchDeleteRequest,
    db: AsyncSession = Depends(get_db),
):
    """Delete multiple chat_attachmentss by their IDs"""
    logger.debug(f"Batch deleting {len(request.ids)} chat_attachmentss")
    
    service = Chat_attachmentsService(db)
    deleted_count = 0
    
    try:
        for item_id in request.ids:
            success = await service.delete(item_id)
            if success:
                deleted_count += 1
        
        logger.info(f"Batch deleted {deleted_count} chat_attachmentss successfully")
        return {"message": f"Successfully deleted {deleted_count} chat_attachmentss", "deleted_count": deleted_count}
    except Exception as e:
        await db.rollback()
        logger.error(f"Error in batch delete: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Batch delete failed: {str(e)}")


@router.delete("/{id}")
async def delete_chat_attachments(
    id: int,
    db: AsyncSession = Depends(get_db),
):
    """Delete a single chat_attachments by ID"""
    logger.debug(f"Deleting chat_attachments with id: {id}")
    
    service = Chat_attachmentsService(db)
    try:
        success = await service.delete(id)
        if not success:
            logger.warning(f"Chat_attachments with id {id} not found for deletion")
            raise HTTPException(status_code=404, detail="Chat_attachments not found")
        
        logger.info(f"Chat_attachments {id} deleted successfully")
        return {"message": "Chat_attachments deleted successfully", "id": id}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting chat_attachments {id}: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")