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_branding import Chat_brandingService

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

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


# ---------- Pydantic Schemas ----------
class Chat_brandingData(BaseModel):
    """Entity data schema (for create/update)"""
    widget_name: str = None
    avatar_url: str = None
    avatar_fallback_initials: str = None
    agent_avatar_url: str = None
    primary_color: str = None
    accent_color: str = None
    bubble_bg_color: str = None
    bubble_text_color: str = None
    header_bg_color: str = None
    header_text_color: str = None
    launcher_style: str = None
    launcher_icon: str = None
    launcher_icon_url: str = None
    launcher_position: str = None
    welcome_message: str = None
    offline_message: str = None
    ai_intro_message: str = None
    human_handover_message: str = None
    input_placeholder: str = None
    show_branding_footer: bool = None
    footer_text: str = None
    enable_sound: bool = None
    notification_sound: str = None
    theme_mode: str = None
    rounded: str = None
    font_family: str = None


class Chat_brandingUpdateData(BaseModel):
    """Update entity data (partial updates allowed)"""
    widget_name: Optional[str] = None
    avatar_url: Optional[str] = None
    avatar_fallback_initials: Optional[str] = None
    agent_avatar_url: Optional[str] = None
    primary_color: Optional[str] = None
    accent_color: Optional[str] = None
    bubble_bg_color: Optional[str] = None
    bubble_text_color: Optional[str] = None
    header_bg_color: Optional[str] = None
    header_text_color: Optional[str] = None
    launcher_style: Optional[str] = None
    launcher_icon: Optional[str] = None
    launcher_icon_url: Optional[str] = None
    launcher_position: Optional[str] = None
    welcome_message: Optional[str] = None
    offline_message: Optional[str] = None
    ai_intro_message: Optional[str] = None
    human_handover_message: Optional[str] = None
    input_placeholder: Optional[str] = None
    show_branding_footer: Optional[bool] = None
    footer_text: Optional[str] = None
    enable_sound: Optional[bool] = None
    notification_sound: Optional[str] = None
    theme_mode: Optional[str] = None
    rounded: Optional[str] = None
    font_family: Optional[str] = None


class Chat_brandingResponse(BaseModel):
    """Entity response schema"""
    id: int
    widget_name: Optional[str] = None
    avatar_url: Optional[str] = None
    avatar_fallback_initials: Optional[str] = None
    agent_avatar_url: Optional[str] = None
    primary_color: Optional[str] = None
    accent_color: Optional[str] = None
    bubble_bg_color: Optional[str] = None
    bubble_text_color: Optional[str] = None
    header_bg_color: Optional[str] = None
    header_text_color: Optional[str] = None
    launcher_style: Optional[str] = None
    launcher_icon: Optional[str] = None
    launcher_icon_url: Optional[str] = None
    launcher_position: Optional[str] = None
    welcome_message: Optional[str] = None
    offline_message: Optional[str] = None
    ai_intro_message: Optional[str] = None
    human_handover_message: Optional[str] = None
    input_placeholder: Optional[str] = None
    show_branding_footer: Optional[bool] = None
    footer_text: Optional[str] = None
    enable_sound: Optional[bool] = None
    notification_sound: Optional[str] = None
    theme_mode: Optional[str] = None
    rounded: Optional[str] = None
    font_family: Optional[str] = None
    created_at: Optional[datetime] = None
    updated_at: Optional[datetime] = None

    class Config:
        from_attributes = True


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


class Chat_brandingBatchCreateRequest(BaseModel):
    """Batch create request"""
    items: List[Chat_brandingData]


class Chat_brandingBatchUpdateItem(BaseModel):
    """Batch update item"""
    id: int
    updates: Chat_brandingUpdateData


class Chat_brandingBatchUpdateRequest(BaseModel):
    """Batch update request"""
    items: List[Chat_brandingBatchUpdateItem]


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


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


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

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


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


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


@router.post("/batch", response_model=List[Chat_brandingResponse], status_code=201)
async def create_chat_brandings_batch(
    request: Chat_brandingBatchCreateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Create multiple chat_brandings in a single request"""
    logger.debug(f"Batch creating {len(request.items)} chat_brandings")
    
    service = Chat_brandingService(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_brandings 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_brandingResponse])
async def update_chat_brandings_batch(
    request: Chat_brandingBatchUpdateRequest,
    db: AsyncSession = Depends(get_db),
):
    """Update multiple chat_brandings in a single request"""
    logger.debug(f"Batch updating {len(request.items)} chat_brandings")
    
    service = Chat_brandingService(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_brandings 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_brandingResponse)
async def update_chat_branding(
    id: int,
    data: Chat_brandingUpdateData,
    db: AsyncSession = Depends(get_db),
):
    """Update an existing chat_branding"""
    logger.debug(f"Updating chat_branding {id} with data: {data}")

    service = Chat_brandingService(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_branding with id {id} not found for update")
            raise HTTPException(status_code=404, detail="Chat_branding not found")
        
        logger.info(f"Chat_branding {id} updated successfully")
        return result
    except HTTPException:
        raise
    except ValueError as e:
        logger.error(f"Validation error updating chat_branding {id}: {str(e)}")
        raise HTTPException(status_code=400, detail=str(e))
    except Exception as e:
        logger.error(f"Error updating chat_branding {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_brandings_batch(
    request: Chat_brandingBatchDeleteRequest,
    db: AsyncSession = Depends(get_db),
):
    """Delete multiple chat_brandings by their IDs"""
    logger.debug(f"Batch deleting {len(request.ids)} chat_brandings")
    
    service = Chat_brandingService(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_brandings successfully")
        return {"message": f"Successfully deleted {deleted_count} chat_brandings", "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_branding(
    id: int,
    db: AsyncSession = Depends(get_db),
):
    """Delete a single chat_branding by ID"""
    logger.debug(f"Deleting chat_branding with id: {id}")
    
    service = Chat_brandingService(db)
    try:
        success = await service.delete(id)
        if not success:
            logger.warning(f"Chat_branding with id {id} not found for deletion")
            raise HTTPException(status_code=404, detail="Chat_branding not found")
        
        logger.info(f"Chat_branding {id} deleted successfully")
        return {"message": "Chat_branding deleted successfully", "id": id}
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error deleting chat_branding {id}: {str(e)}", exc_info=True)
        raise HTTPException(status_code=500, detail=f"Internal server error: {str(e)}")