"""
Beach Design API endpoints for the beach design interface
"""
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import List, Union
from uuid import UUID
from pydantic import BaseModel, validator

from app.db.session import get_db
from app.models.beach import BeachPlace, BeachPlaceTerrain

router = APIRouter()

# Debug test endpoint
@router.get("/debug/{beach_id}")
def debug_beach_design(
    beach_id: UUID,
    db: Session = Depends(get_db)
):
    """Debug endpoint to check beach and terrain data"""
    try:
        from sqlalchemy import text
        
        # Check if beach place exists
        beach_result = db.execute(text("""
            SELECT beach_place_id, beach_name 
            FROM beach_places 
            WHERE beach_place_id = :beach_id
        """), {"beach_id": str(beach_id)})
        
        beach_data = beach_result.fetchone()
        
        # Check total terrain count
        terrain_count = db.execute(text("""
            SELECT COUNT(*) as total_count
            FROM beach_place_terrains
        """)).fetchone()
        
        # Check terrain count for this beach using both column names
        terrain_count_uuid = None
        terrain_count_id = None
        
        try:
            terrain_count_uuid = db.execute(text("""
                SELECT COUNT(*) as count_uuid
                FROM beach_place_terrains
                WHERE beach_place_id = :beach_id
            """), {"beach_id": str(beach_id)}).fetchone()
        except Exception as e:
            terrain_count_uuid = f"Error: {str(e)}"
        
        try:
            terrain_count_id = db.execute(text("""
                SELECT COUNT(*) as count_id
                FROM beach_place_terrains
                WHERE beach_place_id = :beach_id
            """), {"beach_id": str(beach_id)}).fetchone()
        except Exception as e:
            terrain_count_id = f"Error: {str(e)}"
        
        return {
            "beach_id": str(beach_id),
            "beach_exists": beach_data is not None,
            "beach_name": beach_data.beach_name if beach_data else None,
            "total_terrains_in_db": terrain_count.total_count if terrain_count else 0,
            "terrains_with_uuid_fk": terrain_count_uuid.count_uuid if hasattr(terrain_count_uuid, 'count_uuid') else str(terrain_count_uuid),
            "terrains_with_id": terrain_count_id.count_id if hasattr(terrain_count_id, 'count_id') else str(terrain_count_id)
        }
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Debug error: {str(e)}")

# Simple test endpoint that doesn't require database
@router.get("/test")
def test_endpoint():
    """Simple test endpoint to verify API connectivity"""
    return {"status": "success", "message": "Beach design API is working"}

# Root endpoint to handle calls without beach_id
@router.get("/")
def beach_design_root():
    """Beach design API root endpoint"""
    return {
        "message": "Beach Design API",
        "usage": "Please provide a beach_id parameter. Example: /api/beach-design/{beach_id}",
        "endpoints": {
            "GET /api/beach-design/{beach_id}": "Get beach layout data",
            "POST /api/beach-design/{beach_id}": "Update beach layout data",
            "GET /api/beach-design/{beach_id}/{terrain_id}": "Get single terrain item",
            "DELETE /api/beach-design/{beach_id}/{terrain_id}": "Delete terrain item"
        }
    }


class BeachDesignElement(BaseModel):
    CompaniesBeachPlaceTerrainID: str
    uid: int
    CompanyBeachPlaceID: str
    angle: float
    backgroundColor: str
    bedReference: Union[str, int, None] = None  # Allow string, int, or None
    blockOnline: int
    classification: int
    covers: Union[str, None] = None  # Allow string or None
    description: Union[str, None] = None  # Allow string or None
    descriptionText: Union[str, None] = None  # Allow string or None
    descriptionTextPosition: Union[str, None] = None  # Allow string or None
    height: float
    left: float
    bedPrice: float
    minPrice: float
    name: str
    top: float
    width: float
    zindex: int
    islayout: int
    
    @validator('bedReference', pre=True)
    def convert_bed_reference(cls, v):
        """Convert bedReference to string, handling None and numeric values"""
        if v is None:
            return ""
        return str(v)
    
    @validator('covers', 'description', 'descriptionText', 'descriptionTextPosition', pre=True)
    def convert_optional_strings(cls, v):
        """Convert optional string fields, handling None values"""
        if v is None:
            return ""
        return str(v)

class BeachDesignUpdate(BaseModel):
    elements: List[BeachDesignElement]

@router.get("/{beach_id}")
def get_beach_design(
    beach_id: UUID,
    db: Session = Depends(get_db)
):
    """Get beach design layout"""
    try:
        # Use raw SQL query to avoid SQLAlchemy model issues with the migrated database
        from sqlalchemy import text
        
        # Based on admin.py, try beach_place_id column first
        result = db.execute(text("""
            SELECT terrain_id, uid, angle, background_color, bed_reference,
                   block_online, classification, covers, description,
                   description_text, description_text_position, height,
                   left_position, bed_price, min_price, name,
                   top_position, width, z_index, is_layout
            FROM beach_place_terrains 
            WHERE beach_place_id = :beach_id
            ORDER BY z_index ASC
        """), {"beach_id": str(beach_id)})
        
        terrain_data = []
        for terrain in result:
            terrain_data.append({
                "terrain_id": str(terrain.terrain_id),
                "uid": terrain.uid or 0,
                "beach_place_id": str(beach_id),  # Use the beach_id passed in
                "angle": terrain.angle or 0,
                "background_color": terrain.background_color or "",
                "bed_reference": terrain.bed_reference or "",
                "block_online": 1 if terrain.block_online else 0,
                "classification": terrain.classification or 0,
                "covers": terrain.covers or "",
                "description": terrain.description or "",
                "description_text": terrain.description_text or "",
                "description_text_position": terrain.description_text_position or "",
                "height": float(terrain.height or 0),
                "left_position": float(terrain.left_position or 0),
                "bed_price": float(terrain.bed_price or 0),
                "min_price": float(terrain.min_price or 0),
                "name": terrain.name or "",  
                "top_position": float(terrain.top_position or 0),
                "width": float(terrain.width or 0),
                "z_index": terrain.z_index or 0,
                "is_layout": 1 if terrain.is_layout else 0
            })
        
        return terrain_data
        
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"Error getting beach design: {str(e)}")

@router.post("/{beach_id}")
def update_beach_design(
    beach_id: UUID,
    design_data: BeachDesignUpdate,
    db: Session = Depends(get_db)
):
    """Update beach design layout"""
    from sqlalchemy import text
    
    # Verify beach place exists
    beach_check = db.execute(text("""
        SELECT beach_place_id FROM beach_places WHERE beach_place_id = :beach_id
    """), {"beach_id": str(beach_id)}).fetchone()
    
    if not beach_check:
        raise HTTPException(status_code=404, detail="Beach place not found")
    
    # Process each element in the update
    for element in design_data.elements:
        terrain_id = element.CompaniesBeachPlaceTerrainID
        
        # Check if terrain exists
        existing_terrain = db.execute(text("""
            SELECT terrain_id FROM beach_place_terrains 
            WHERE terrain_id = :terrain_id
        """), {"terrain_id": terrain_id}).fetchone()
        
        if existing_terrain:
            # Update existing terrain
            db.execute(text("""
                UPDATE beach_place_terrains SET
                    uid = :uid,
                    angle = :angle,
                    background_color = :background_color,
                    bed_reference = :bed_reference,
                    block_online = :block_online,
                    classification = :classification,
                    covers = :covers,
                    description = :description,
                    description_text = :description_text,
                    description_text_position = :description_text_position,
                    height = :height,
                    left_position = :left_position,
                    bed_price = :bed_price,
                    min_price = :min_price,
                    name = :name,
                    top_position = :top_position,
                    width = :width,
                    z_index = :z_index,
                    is_layout = :is_layout
                WHERE terrain_id = :terrain_id
            """), {
                "terrain_id": terrain_id,
                "uid": element.uid,
                "angle": int(element.angle),
                "background_color": element.backgroundColor,
                "bed_reference": element.bedReference,
                "block_online": bool(element.blockOnline),
                "classification": element.classification,
                "covers": element.covers,
                "description": element.description,
                "description_text": element.descriptionText,
                "description_text_position": element.descriptionTextPosition,
                "height": element.height,
                "left_position": element.left,
                "bed_price": element.bedPrice,
                "min_price": element.minPrice,
                "name": element.name,
                "top_position": element.top,
                "width": element.width,
                "z_index": element.zindex,
                "is_layout": bool(element.islayout)
            })
        else:
            # Create new terrain using the correct column name
            db.execute(text("""
                INSERT INTO beach_place_terrains (
                    terrain_id, uid, beach_place_id, angle, background_color,
                    bed_reference, block_online, classification, covers,
                    description, description_text, description_text_position,
                    height, left_position, bed_price, min_price, name,
                    top_position, width, z_index, is_layout
                ) VALUES (
                    :terrain_id, :uid, :beach_place_id, :angle, :background_color,
                    :bed_reference, :block_online, :classification, :covers,
                    :description, :description_text, :description_text_position,
                    :height, :left_position, :bed_price, :min_price, :name,
                    :top_position, :width, :z_index, :is_layout
                )
            """), {
                "terrain_id": terrain_id,
                "uid": element.uid,
                "beach_place_id": str(beach_id),
                "angle": int(element.angle),
                "background_color": element.backgroundColor,
                "bed_reference": element.bedReference,
                "block_online": bool(element.blockOnline),
                "classification": element.classification,
                "covers": element.covers,
                "description": element.description,
                "description_text": element.descriptionText,
                "description_text_position": element.descriptionTextPosition,
                "height": element.height,
                "left_position": element.left,
                "bed_price": element.bedPrice,
                "min_price": element.minPrice,
                "name": element.name,
                "top_position": element.top,
                "width": element.width,
                "z_index": element.zindex,
                "is_layout": bool(element.islayout)
            })
    
    db.commit()
    return {"message": "Beach design updated successfully"}

@router.get("/{beach_id}/{terrain_id}")
def get_single_beach_terrain(
    beach_id: UUID,
    terrain_id: UUID,
    db: Session = Depends(get_db)
):
    """Get single beach terrain item"""
    from sqlalchemy import text
    
    result = db.execute(text("""
        SELECT terrain_id, uid, angle, background_color, bed_reference,
               block_online, classification, covers, description,
               description_text, description_text_position, height,
               left_position, bed_price, min_price, name,
               top_position, width, z_index, is_layout
        FROM beach_place_terrains 
        WHERE beach_place_id = :beach_id AND terrain_id = :terrain_id
    """), {"beach_id": str(beach_id), "terrain_id": str(terrain_id)})
    
    terrain = result.fetchone()
    
    if not terrain:
        raise HTTPException(status_code=404, detail="Beach terrain not found")
    
    return {
        "terrain_id": str(terrain.terrain_id),
        "uid": terrain.uid or 0,
        "beach_place_id": str(beach_id),
        "angle": terrain.angle or 0,
        "background_color": terrain.background_color or "",
        "bed_reference": terrain.bed_reference or "",
        "block_online": 1 if terrain.block_online else 0,
        "classification": terrain.classification or 0,
        "covers": terrain.covers or "",
        "description": terrain.description or "",
        "description_text": terrain.description_text or "",
        "description_text_position": terrain.description_text_position or "",
        "height": float(terrain.height or 0),
        "left_position": float(terrain.left_position or 0),
        "bed_price": float(terrain.bed_price or 0),
        "min_price": float(terrain.min_price or 0),
        "name": terrain.name or "",
        "top_position": float(terrain.top_position or 0),
        "width": float(terrain.width or 0),
        "z_index": terrain.z_index or 0,
        "is_layout": 1 if terrain.is_layout else 0
    }

@router.delete("/{beach_id}/{terrain_id}")
def delete_beach_terrain(
    beach_id: UUID,
    terrain_id: UUID,
    db: Session = Depends(get_db)
):
    """Delete beach terrain item"""
    from sqlalchemy import text
    
    # Check if terrain exists first
    check_result = db.execute(text("""
        SELECT terrain_id 
        FROM beach_place_terrains 
        WHERE beach_place_id = :beach_id AND terrain_id = :terrain_id
    """), {"beach_id": str(beach_id), "terrain_id": str(terrain_id)})
    
    if not check_result.fetchone():
        raise HTTPException(status_code=404, detail="Beach terrain not found")
    
    # Delete the terrain
    db.execute(text("""
        DELETE FROM beach_place_terrains 
        WHERE beach_place_id = :beach_id AND terrain_id = :terrain_id
    """), {"beach_id": str(beach_id), "terrain_id": str(terrain_id)})
    
    db.commit()
    
    return {"message": "Beach terrain deleted successfully"}