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.agent_availability import Agent_availabilityService

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

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


# ---------- Pydantic Schemas ----------
class Agent_availabilityData(BaseModel):
    """Entity data schema (for create/update)"""
    seat_id: int
    status: str
    last_heartbeat_at: Optional[datetime] = None


class Agent_availabilityUpdateData(BaseModel):
    """Update entity data (partial updates allowed)"""
    seat_id: Optional[int] = None
    status: Optional[str] = None
    last_heartbeat_at: Optional[datetime] = None


class Agent_availabilityResponse(BaseModel):
    """Entity response schema"""
    id: int
    seat_id: int
    status: str
    last_heartbeat_at: Optional[datetime] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


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


class Agent_availabilityBatchCreateRequest(BaseModel):
    """Batch create request"""
    items: List[Agent_availabilityData]


class Agent_availabilityBatchUpdateItem(BaseModel):
    """Batch update item"""
    id: int
    updates: Agent_availabilityUpdateData


class Agent_availabilityBatchUpdateRequest(BaseModel):
    """Batch update request"""
    items: List[Agent_availabilityBatchUpdateItem]


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


# ---------- Routes ----------
@router.get("", response_model=Agent_availabilityListResponse)
async def query_agent_availabilitys(
    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 agent_availabilitys with filtering, sorting, and pagination"""
    logger.debug(f"Querying agent_availabilitys: query={query}, sort={sort}, skip={skip}, limit={limit}, fields={fields}")
    
    service = Agent_availabilityService(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']} agent_availabilitys")
        return result
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error querying agent_availabilitys: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.get("/all", response_model=Agent_availabilityListResponse)
async def query_agent_availabilitys_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 agent_availabilitys with filtering, sorting, and pagination without user limitation
    logger.debug(f"Querying agent_availabilitys: query={query}, sort={sort}, skip={skip}, limit={limit}, fields={fields}")

    service = Agent_availabilityService(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']} agent_availabilitys")
        return result
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error querying agent_availabilitys: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


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


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


@router.post("/batch", response_model=List[Agent_availabilityResponse], status_code=201)
async def create_agent_availabilitys_batch(
    request: Agent_availabilityBatchCreateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Create multiple agent_availabilitys in a single request"""
    logger.debug(f"Batch creating {len(request.items)} agent_availabilitys")
    
    service = Agent_availabilityService(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)} agent_availabilitys 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[Agent_availabilityResponse])
async def update_agent_availabilitys_batch(
    request: Agent_availabilityBatchUpdateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Update multiple agent_availabilitys in a single request"""
    logger.debug(f"Batch updating {len(request.items)} agent_availabilitys")
    
    service = Agent_availabilityService(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)} agent_availabilitys 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=Agent_availabilityResponse)
async def update_agent_availability(
    id: int,
    data: Agent_availabilityUpdateData,
    db: AsyncSession = Depends(get_db),
):
    """Update an existing agent_availability"""
    logger.debug(f"Updating agent_availability {id} with data: {data}")

    service = Agent_availabilityService(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"Agent_availability with id {id} not found for update")
            raise HTTPException(status_code=404, detail="Agent_availability not found")
        
        logger.info(f"Agent_availability {id} updated successfully")
        return result
    except HTTPException:
        raise
    except ValueError as e:
        logger.error(f"Validation error updating agent_availability {id}: {str(e)}")
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Error updating agent_availability {id}: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")


@router.delete("/batch")
async def delete_agent_availabilitys_batch(
    request: Agent_availabilityBatchDeleteRequest,
    db: AsyncSession = Depends(get_db),
):
    """Delete multiple agent_availabilitys by their IDs"""
    logger.debug(f"Batch deleting {len(request.ids)} agent_availabilitys")
    
    service = Agent_availabilityService(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} agent_availabilitys successfully")
        return {"message": f"Successfully deleted {deleted_count} agent_availabilitys", "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_agent_availability(
    id: int,
    db: AsyncSession = Depends(get_db),
):
    """Delete a single agent_availability by ID"""
    logger.debug(f"Deleting agent_availability with id: {id}")
    
    service = Agent_availabilityService(db)
    try:
        success = await service.delete(id)
        if not success:
            logger.warning(f"Agent_availability with id {id} not found for deletion")
            raise HTTPException(status_code=404, detail="Agent_availability not found")
        
        logger.info(f"Agent_availability {id} deleted successfully")
        return {"message": "Agent_availability deleted successfully", "id": id}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting agent_availability {id}: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")