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.presales_messages import Presales_messagesService

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

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


# ---------- Pydantic Schemas ----------
class Presales_messagesData(BaseModel):
    """Entity data schema (for create/update)"""
    name: str
    email: str
    phone: str = None
    company: str = None
    source_page: str
    topic: str = None
    message: str
    status: str = None
    user_agent: str = None
    referrer: str = None


class Presales_messagesUpdateData(BaseModel):
    """Update entity data (partial updates allowed)"""
    name: Optional[str] = None
    email: Optional[str] = None
    phone: Optional[str] = None
    company: Optional[str] = None
    source_page: Optional[str] = None
    topic: Optional[str] = None
    message: Optional[str] = None
    status: Optional[str] = None
    user_agent: Optional[str] = None
    referrer: Optional[str] = None


class Presales_messagesResponse(BaseModel):
    """Entity response schema"""
    id: int
    name: str
    email: str
    phone: Optional[str] = None
    company: Optional[str] = None
    source_page: str
    topic: Optional[str] = None
    message: str
    status: Optional[str] = None
    user_agent: Optional[str] = None
    referrer: Optional[str] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


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


class Presales_messagesBatchCreateRequest(BaseModel):
    """Batch create request"""
    items: List[Presales_messagesData]


class Presales_messagesBatchUpdateItem(BaseModel):
    """Batch update item"""
    id: int
    updates: Presales_messagesUpdateData


class Presales_messagesBatchUpdateRequest(BaseModel):
    """Batch update request"""
    items: List[Presales_messagesBatchUpdateItem]


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


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


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

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


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


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


@router.post("/batch", response_model=List[Presales_messagesResponse], status_code=201)
async def create_presales_messagess_batch(
    request: Presales_messagesBatchCreateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Create multiple presales_messagess in a single request"""
    logger.debug(f"Batch creating {len(request.items)} presales_messagess")
    
    service = Presales_messagesService(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)} presales_messagess 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[Presales_messagesResponse])
async def update_presales_messagess_batch(
    request: Presales_messagesBatchUpdateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Update multiple presales_messagess in a single request"""
    logger.debug(f"Batch updating {len(request.items)} presales_messagess")
    
    service = Presales_messagesService(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)} presales_messagess 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=Presales_messagesResponse)
async def update_presales_messages(
    id: int,
    data: Presales_messagesUpdateData,
    db: AsyncSession = Depends(get_db),
):
    """Update an existing presales_messages"""
    logger.debug(f"Updating presales_messages {id} with data: {data}")

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


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