"""
Price Alert API endpoints.

Allows users to subscribe to TLD price notifications.

Endpoints:
- GET /price-alerts - List user's price alerts
- POST /price-alerts - Create new price alert
- GET /price-alerts/{tld} - Get alert for specific TLD
- PUT /price-alerts/{tld} - Update alert settings
- DELETE /price-alerts/{tld} - Delete alert
"""
import logging
from datetime import datetime
from typing import Optional, List

from fastapi import APIRouter, HTTPException, status
from pydantic import BaseModel, Field
from sqlalchemy import select, delete

from app.api.deps import Database, CurrentUser, CurrentUserOptional
from app.models.price_alert import PriceAlert

logger = logging.getLogger(__name__)

router = APIRouter()


# ============== Schemas ==============

class PriceAlertCreate(BaseModel):
    """Create a new price alert."""
    tld: str = Field(..., min_length=1, max_length=50, description="TLD without dot (e.g., 'com')")
    target_price: Optional[float] = Field(None, ge=0, description="Alert when price drops below this")
    threshold_percent: float = Field(5.0, ge=1, le=50, description="Alert on % change (default 5%)")


class PriceAlertUpdate(BaseModel):
    """Update price alert settings."""
    is_active: Optional[bool] = None
    target_price: Optional[float] = Field(None, ge=0)
    threshold_percent: Optional[float] = Field(None, ge=1, le=50)


class PriceAlertResponse(BaseModel):
    """Price alert response."""
    id: int
    tld: str
    is_active: bool
    target_price: Optional[float]
    threshold_percent: float
    last_notified_at: Optional[datetime]
    last_notified_price: Optional[float]
    created_at: datetime

    class Config:
        from_attributes = True


class PriceAlertStatus(BaseModel):
    """Status check for a TLD alert (for unauthenticated users)."""
    tld: str
    has_alert: bool
    is_active: bool = False


# ============== Endpoints ==============

@router.get("", response_model=List[PriceAlertResponse])
async def list_price_alerts(
    current_user: CurrentUser,
    db: Database,
    active_only: bool = False,
):
    """
    List all price alerts for the current user.
    
    Args:
        active_only: If true, only return active alerts
    """
    query = select(PriceAlert).where(PriceAlert.user_id == current_user.id)
    
    if active_only:
        query = query.where(PriceAlert.is_active == True)
    
    query = query.order_by(PriceAlert.created_at.desc())
    
    result = await db.execute(query)
    alerts = result.scalars().all()
    
    return alerts


@router.post("", response_model=PriceAlertResponse, status_code=status.HTTP_201_CREATED)
async def create_price_alert(
    alert_data: PriceAlertCreate,
    current_user: CurrentUser,
    db: Database,
):
    """
    Create a new price alert for a TLD.
    
    - One alert per TLD per user
    - Default threshold: 5% price change
    - Optional: set target price to only alert below threshold
    """
    tld = alert_data.tld.lower().strip().lstrip(".")
    
    # Check if alert already exists
    existing = await db.execute(
        select(PriceAlert).where(
            PriceAlert.user_id == current_user.id,
            PriceAlert.tld == tld,
        )
    )
    if existing.scalar_one_or_none():
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"You already have a price alert for .{tld}",
        )
    
    # Create alert
    alert = PriceAlert(
        user_id=current_user.id,
        tld=tld,
        target_price=alert_data.target_price,
        threshold_percent=alert_data.threshold_percent,
        is_active=True,
    )
    
    db.add(alert)
    await db.commit()
    await db.refresh(alert)
    
    logger.info(f"User {current_user.id} created price alert for .{tld}")
    
    return alert


@router.get("/status/{tld}", response_model=PriceAlertStatus)
async def get_alert_status(
    tld: str,
    current_user: CurrentUserOptional,
    db: Database,
):
    """
    Check if user has an alert for a specific TLD.
    
    Works for both authenticated and unauthenticated users.
    Returns has_alert=False for unauthenticated users.
    """
    tld = tld.lower().strip().lstrip(".")
    
    if not current_user:
        return PriceAlertStatus(tld=tld, has_alert=False)
    
    result = await db.execute(
        select(PriceAlert).where(
            PriceAlert.user_id == current_user.id,
            PriceAlert.tld == tld,
        )
    )
    alert = result.scalar_one_or_none()
    
    if not alert:
        return PriceAlertStatus(tld=tld, has_alert=False)
    
    return PriceAlertStatus(
        tld=tld,
        has_alert=True,
        is_active=alert.is_active,
    )


@router.get("/{tld}", response_model=PriceAlertResponse)
async def get_price_alert(
    tld: str,
    current_user: CurrentUser,
    db: Database,
):
    """Get price alert for a specific TLD."""
    tld = tld.lower().strip().lstrip(".")
    
    result = await db.execute(
        select(PriceAlert).where(
            PriceAlert.user_id == current_user.id,
            PriceAlert.tld == tld,
        )
    )
    alert = result.scalar_one_or_none()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"No price alert found for .{tld}",
        )
    
    return alert


@router.put("/{tld}", response_model=PriceAlertResponse)
async def update_price_alert(
    tld: str,
    update_data: PriceAlertUpdate,
    current_user: CurrentUser,
    db: Database,
):
    """Update price alert settings."""
    tld = tld.lower().strip().lstrip(".")
    
    result = await db.execute(
        select(PriceAlert).where(
            PriceAlert.user_id == current_user.id,
            PriceAlert.tld == tld,
        )
    )
    alert = result.scalar_one_or_none()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"No price alert found for .{tld}",
        )
    
    # Update fields
    if update_data.is_active is not None:
        alert.is_active = update_data.is_active
    if update_data.target_price is not None:
        alert.target_price = update_data.target_price
    if update_data.threshold_percent is not None:
        alert.threshold_percent = update_data.threshold_percent
    
    await db.commit()
    await db.refresh(alert)
    
    return alert


@router.delete("/{tld}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_price_alert(
    tld: str,
    current_user: CurrentUser,
    db: Database,
):
    """Delete a price alert."""
    tld = tld.lower().strip().lstrip(".")
    
    result = await db.execute(
        select(PriceAlert).where(
            PriceAlert.user_id == current_user.id,
            PriceAlert.tld == tld,
        )
    )
    alert = result.scalar_one_or_none()
    
    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"No price alert found for .{tld}",
        )
    
    await db.execute(
        delete(PriceAlert).where(PriceAlert.id == alert.id)
    )
    await db.commit()
    
    logger.info(f"User {current_user.id} deleted price alert for .{tld}")


@router.post("/{tld}/toggle", response_model=PriceAlertResponse)
async def toggle_price_alert(
    tld: str,
    current_user: CurrentUser,
    db: Database,
):
    """
    Toggle a price alert on/off.
    
    If alert exists, toggles is_active.
    If alert doesn't exist, creates a new one.
    """
    tld = tld.lower().strip().lstrip(".")
    
    result = await db.execute(
        select(PriceAlert).where(
            PriceAlert.user_id == current_user.id,
            PriceAlert.tld == tld,
        )
    )
    alert = result.scalar_one_or_none()
    
    if alert:
        # Toggle existing alert
        alert.is_active = not alert.is_active
        await db.commit()
        await db.refresh(alert)
        logger.info(f"User {current_user.id} toggled alert for .{tld} to {alert.is_active}")
    else:
        # Create new alert
        alert = PriceAlert(
            user_id=current_user.id,
            tld=tld,
            is_active=True,
            threshold_percent=5.0,
        )
        db.add(alert)
        await db.commit()
        await db.refresh(alert)
        logger.info(f"User {current_user.id} created new price alert for .{tld}")
    
    return alert

