"""Alerts API endpoints - 告警通知接口"""
import logging
import uuid

from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy import select, func, and_
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_current_user
from app.database import get_db
from app.models.alert import Alert
from app.models.alert_setting import AlertSetting
from app.models.brand import Brand
from app.models.user import User
from app.schemas.alert import (
    AlertResponse,
    AlertListResponse,
    AlertUnreadCountResponse,
    AlertReadResponse,
    AlertReadAllResponse,
    AlertSettingResponse,
    AlertSettingUpdate,
    AlertSettingCreate,
    AlertSettingListResponse,
    AlertSettingBulkUpdate,
)
from app.services.alert_engine import AlertEngine

logger = logging.getLogger(__name__)

router = APIRouter()


async def verify_brand_ownership(
    brand_id: uuid.UUID,
    current_user: User,
    db: AsyncSession,
) -> Brand:
    """验证品牌属于当前用户"""
    stmt = select(Brand).where(
        and_(
            Brand.id == brand_id,
            Brand.user_id == current_user.id,
        )
    )
    result = await db.execute(stmt)
    brand = result.scalar_one_or_none()

    if not brand:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail=f"品牌 {brand_id} 不存在或不属于当前用户",
        )

    return brand


# ============================================================
# 告警接口
# ============================================================

@router.get("/", response_model=AlertListResponse)
async def get_alerts(
    skip: int = Query(0, ge=0, description="跳过条数"),
    limit: int = Query(20, ge=1, le=100, description="每页条数"),
    alert_type: str | None = Query(None, description="按告警类型筛选"),
    severity: str | None = Query(None, description="按严重程度筛选"),
    is_read: bool | None = Query(None, description="按已读状态筛选"),
    brand_id: uuid.UUID | None = Query(None, description="按品牌筛选"),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """
    获取当前用户的告警列表

    支持按类型、严重程度、已读状态和品牌筛选，按创建时间倒序排列。
    """
    # 构建查询条件
    conditions = [Alert.user_id == current_user.id]
    if alert_type:
        conditions.append(Alert.alert_type == alert_type)
    if severity:
        conditions.append(Alert.severity == severity)
    if is_read is not None:
        conditions.append(Alert.is_read == is_read)
    if brand_id:
        conditions.append(Alert.brand_id == brand_id)

    # 查询总数
    count_stmt = select(func.count()).select_from(Alert).where(and_(*conditions))
    count_result = await db.execute(count_stmt)
    total = count_result.scalar_one()

    # 查询列表
    stmt = (
        select(Alert)
        .where(and_(*conditions))
        .order_by(Alert.created_at.desc())
        .offset(skip)
        .limit(limit)
    )
    result = await db.execute(stmt)
    alerts = list(result.scalars().all())

    return {"items": alerts, "total": total}


@router.get("/unread-count", response_model=AlertUnreadCountResponse)
async def get_unread_count(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """获取当前用户的未读告警数量"""
    stmt = select(func.count()).select_from(Alert).where(
        and_(
            Alert.user_id == current_user.id,
            Alert.is_read == False,
        )
    )
    result = await db.execute(stmt)
    count = result.scalar_one()

    return {"unread_count": count}


@router.patch("/read-all", response_model=AlertReadAllResponse)
async def mark_all_read(
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """将当前用户的所有告警标记为已读"""
    stmt = select(Alert).where(
        and_(
            Alert.user_id == current_user.id,
            Alert.is_read == False,
        )
    )
    result = await db.execute(stmt)
    unread_alerts = list(result.scalars().all())

    updated_count = 0
    for alert in unread_alerts:
        alert.is_read = True
        updated_count += 1

    await db.commit()

    return {"updated_count": updated_count}


@router.patch("/{alert_id}/read", response_model=AlertReadResponse)
async def mark_read(
    alert_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """标记指定告警为已读"""
    stmt = select(Alert).where(
        and_(
            Alert.id == alert_id,
            Alert.user_id == current_user.id,
        )
    )
    result = await db.execute(stmt)
    alert = result.scalar_one_or_none()

    if not alert:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="告警不存在",
        )

    alert.is_read = True
    await db.commit()
    await db.refresh(alert)

    return alert


# ============================================================
# 告警设置接口
# ============================================================

@router.get("/settings", response_model=AlertSettingListResponse)
async def get_alert_settings(
    brand_id: uuid.UUID | None = Query(None, description="按品牌筛选"),
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """
    获取当前用户的告警设置

    如果指定 brand_id，则返回该品牌的告警设置；
    否则返回所有品牌的告警设置。
    """
    conditions = [AlertSetting.user_id == current_user.id]
    if brand_id:
        conditions.append(AlertSetting.brand_id == brand_id)

    # 如果指定了品牌但该品牌没有设置，则自动初始化默认设置
    if brand_id:
        engine = AlertEngine(db)
        await engine.ensure_default_settings(brand_id, current_user.id)

    count_stmt = select(func.count()).select_from(AlertSetting).where(and_(*conditions))
    count_result = await db.execute(count_stmt)
    total = count_result.scalar_one()

    stmt = (
        select(AlertSetting)
        .where(and_(*conditions))
        .order_by(AlertSetting.brand_id, AlertSetting.alert_type)
    )
    result = await db.execute(stmt)
    settings = list(result.scalars().all())

    return {"items": settings, "total": total}


@router.put("/settings", response_model=AlertSettingListResponse)
async def update_alert_settings(
    data: AlertSettingBulkUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """
    批量更新告警设置

    接收一组告警设置，对每条记录进行 upsert 操作：
    - 如果品牌+类型组合已存在，则更新
    - 如果不存在，则创建
    """
    engine = AlertEngine(db)
    updated_settings: list[AlertSetting] = []

    for item in data.settings:
        # 验证品牌属于当前用户
        await verify_brand_ownership(item.brand_id, current_user, db)

        # 查找现有设置
        existing_stmt = select(AlertSetting).where(
            and_(
                AlertSetting.brand_id == item.brand_id,
                AlertSetting.alert_type == item.alert_type,
            )
        )
        existing_result = await db.execute(existing_stmt)
        existing = existing_result.scalar_one_or_none()

        if existing:
            # 更新
            existing.enabled = item.enabled
            if item.threshold is not None:
                existing.threshold = item.threshold
            updated_settings.append(existing)
        else:
            # 创建
            setting = AlertSetting(
                brand_id=item.brand_id,
                user_id=current_user.id,
                alert_type=item.alert_type,
                enabled=item.enabled,
                threshold=item.threshold,
            )
            db.add(setting)
            updated_settings.append(setting)

    await db.commit()

    # 刷新所有设置以获取最新数据
    for setting in updated_settings:
        await db.refresh(setting)

    logger.info(f"批量更新告警设置: user={current_user.id}, count={len(updated_settings)}")
    return {"items": updated_settings, "total": len(updated_settings)}


@router.put("/settings/{setting_id}", response_model=AlertSettingResponse)
async def update_single_setting(
    setting_id: uuid.UUID,
    data: AlertSettingUpdate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """更新单条告警设置"""
    stmt = select(AlertSetting).where(
        and_(
            AlertSetting.id == setting_id,
            AlertSetting.user_id == current_user.id,
        )
    )
    result = await db.execute(stmt)
    setting = result.scalar_one_or_none()

    if not setting:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="告警设置不存在",
        )

    # 更新提供的字段
    update_data = data.model_dump(exclude_unset=True)
    for field, value in update_data.items():
        setattr(setting, field, value)

    await db.commit()
    await db.refresh(setting)

    return setting


@router.post("/settings", response_model=AlertSettingResponse, status_code=status.HTTP_201_CREATED)
async def create_alert_setting(
    data: AlertSettingCreate,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """创建告警设置"""
    # 验证品牌属于当前用户
    await verify_brand_ownership(data.brand_id, current_user, db)

    # 检查是否已存在相同品牌+类型的设置
    existing_stmt = select(AlertSetting).where(
        and_(
            AlertSetting.brand_id == data.brand_id,
            AlertSetting.alert_type == data.alert_type,
        )
    )
    existing_result = await db.execute(existing_stmt)
    existing = existing_result.scalar_one_or_none()

    if existing:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=f"品牌 {data.brand_id} 的告警类型 {data.alert_type} 已存在",
        )

    # 创建新设置
    setting = AlertSetting(
        brand_id=data.brand_id,
        user_id=current_user.id,
        alert_type=data.alert_type,
        enabled=data.enabled,
        threshold=data.threshold,
    )
    db.add(setting)
    await db.commit()
    await db.refresh(setting)

    logger.info(f"创建告警设置: user={current_user.id}, brand={data.brand_id}, type={data.alert_type}")
    return setting


@router.delete("/settings/{setting_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_alert_setting(
    setting_id: uuid.UUID,
    current_user: User = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
):
    """删除告警设置"""
    stmt = select(AlertSetting).where(
        and_(
            AlertSetting.id == setting_id,
            AlertSetting.user_id == current_user.id,
        )
    )
    result = await db.execute(stmt)
    setting = result.scalar_one_or_none()

    if not setting:
        raise HTTPException(
            status_code=status.HTTP_404_NOT_FOUND,
            detail="告警设置不存在",
        )

    await db.delete(setting)
    await db.commit()

    logger.info(f"删除告警设置: user={current_user.id}, setting={setting_id}")
    return None
