from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.db.models import User, Notification, Template, Segment, Customer
from app.api.deps import get_current_user
from app.api.schemas import NotificationSend, NotificationOut
from app.services.idempotency import IdempotencyService
from app.services.rate_limiter import RateLimiter
from app.workers.notifications import enqueue_notification
from app.core.config import get_settings

router = APIRouter(prefix="/notifications", tags=["notifications"])


@router.post("/send", response_model=NotificationOut, status_code=201)
def send_notification(
    data: NotificationSend,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    settings = get_settings()
    
    # Rate limiting на создание уведомлений (на уровне тенанта)
    limiter = RateLimiter()
    rate_key = f"notification_creation:tenant:{current_user.tenant_id}"
    
    # Используем специальные настройки для rate limiting создания уведомлений
    allowed = limiter.check_and_consume(
        rate_key,
        tokens=1,
        bucket_size=settings.NOTIFICATION_CREATION_RATE_LIMIT_BUCKET_SIZE,
        refill_rate=settings.NOTIFICATION_CREATION_RATE_LIMIT_REFILL_RATE_PER_SEC
    )
    if not allowed:
        raise HTTPException(
            status_code=429,
            detail="Слишком много запросов на создание уведомлений. Пожалуйста, попробуйте позже."
        )
    
    # Check idempotency
    if data.idempotency_key:
        existing = IdempotencyService.check_idempotency(
            db, current_user.tenant_id, data.idempotency_key
        )
        if existing:
            return existing
    
    # Verify template belongs to tenant
    template = (
        db.query(Template)
        .filter(Template.id == data.template_id, Template.tenant_id == current_user.tenant_id)
        .first()
    )
    if not template:
        raise HTTPException(status_code=404, detail="Шаблон не найден")
    
    # Проверка количества получателей если используется сегмент
    recipients_count = 1  # По умолчанию один получатель (customer_id)
    
    if data.segment_id:
        segment = (
            db.query(Segment)
            .filter(Segment.id == data.segment_id, Segment.tenant_id == current_user.tenant_id)
            .first()
        )
        if not segment:
            raise HTTPException(status_code=404, detail="Сегмент не найден")
        
        # Подсчитываем количество получателей в сегменте
        filter_config = segment.filter or {}
        query = db.query(Customer).filter(Customer.tenant_id == current_user.tenant_id)
        
        if "tags" in filter_config:
            query = query.filter(Customer.tags.overlap(filter_config["tags"]))
        
        recipients_count = query.count()
        
        # Проверяем лимит на количество получателей
        if recipients_count > settings.MAX_RECIPIENTS_PER_NOTIFICATION:
            raise HTTPException(
                status_code=400,
                detail=f"Сегмент содержит слишком много получателей ({recipients_count}). "
                       f"Максимально разрешено: {settings.MAX_RECIPIENTS_PER_NOTIFICATION}"
            )
    elif data.customer_id:
        # Проверяем что клиент существует и принадлежит тенанту
        customer = (
            db.query(Customer)
            .filter(Customer.id == data.customer_id, Customer.tenant_id == current_user.tenant_id)
            .first()
        )
        if not customer:
            raise HTTPException(status_code=404, detail="Клиент не найден")
    else:
        raise HTTPException(
            status_code=400,
            detail="Необходимо указать либо customer_id, либо segment_id"
        )
    
    # Create notification
    notification = Notification(
        tenant_id=current_user.tenant_id,
        template_id=data.template_id,
        customer_id=data.customer_id,
        segment_id=data.segment_id,
        payload=data.payload,
        scheduled_at=data.scheduled_at,
        idempotency_key=data.idempotency_key,
        status="pending",
    )
    db.add(notification)
    db.commit()
    db.refresh(notification)
    
    # Enqueue to Celery
    enqueue_notification.delay(notification.id)
    
    return notification


@router.get("", response_model=list[NotificationOut])
def list_notifications(
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
    skip: int = 0,
    limit: int = 100,
):
    notifications = (
        db.query(Notification)
        .filter(Notification.tenant_id == current_user.tenant_id)
        .order_by(Notification.created_at.desc())
        .offset(skip)
        .limit(limit)
        .all()
    )
    return notifications


@router.get("/{notification_id}", response_model=NotificationOut)
def get_notification(
    notification_id: int,
    current_user: User = Depends(get_current_user),
    db: Session = Depends(get_db),
):
    notification = (
        db.query(Notification)
        .filter(Notification.id == notification_id, Notification.tenant_id == current_user.tenant_id)
        .first()
    )
    if not notification:
        raise HTTPException(status_code=404, detail="Уведомление не найдено")
    return notification
