from __future__ import annotations

from datetime import UTC, datetime

from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.database.models import Webhook, WebhookDelivery


async def create_webhook(
    db: AsyncSession,
    name: str,
    url: str,
    event_type: str,
    secret: str | None = None,
    description: str | None = None,
) -> Webhook:
    """Создать новый webhook."""
    webhook = Webhook(
        name=name,
        url=url,
        event_type=event_type,
        secret=secret,
        description=description,
        is_active=True,
    )
    db.add(webhook)
    await db.commit()
    await db.refresh(webhook)
    return webhook


async def get_webhook_by_id(db: AsyncSession, webhook_id: int) -> Webhook | None:
    """Получить webhook по ID."""
    result = await db.execute(select(Webhook).where(Webhook.id == webhook_id))
    return result.scalar_one_or_none()


async def list_webhooks(
    db: AsyncSession,
    event_type: str | None = None,
    is_active: bool | None = None,
    limit: int = 100,
    offset: int = 0,
) -> tuple[list[Webhook], int]:
    """Список webhooks с фильтрами."""
    query = select(Webhook)

    if event_type:
        query = query.where(Webhook.event_type == event_type)
    if is_active is not None:
        query = query.where(Webhook.is_active == is_active)

    # Подсчет общего количества
    count_query = select(func.count()).select_from(query.subquery())
    total = await db.scalar(count_query) or 0

    # Получение данных
    query = query.order_by(Webhook.created_at.desc()).offset(offset).limit(limit)
    result = await db.execute(query)
    webhooks = result.scalars().all()

    return list(webhooks), int(total)


async def get_active_webhooks_for_event(
    db: AsyncSession,
    event_type: str,
) -> list[Webhook]:
    """Получить все активные webhooks для конкретного события."""
    result = await db.execute(select(Webhook).where(Webhook.event_type == event_type).where(Webhook.is_active == True))
    return list(result.scalars().all())


async def update_webhook(
    db: AsyncSession,
    webhook: Webhook,
    name: str | None = None,
    url: str | None = None,
    secret: str | None = None,
    description: str | None = None,
    is_active: bool | None = None,
) -> Webhook:
    """Обновить webhook."""
    if name is not None:
        webhook.name = name
    if url is not None:
        webhook.url = url
    if secret is not None:
        webhook.secret = secret
    if description is not None:
        webhook.description = description
    if is_active is not None:
        webhook.is_active = is_active

    webhook.updated_at = datetime.now(UTC)
    await db.commit()
    await db.refresh(webhook)
    return webhook


async def delete_webhook(db: AsyncSession, webhook: Webhook) -> None:
    """Удалить webhook."""
    await db.delete(webhook)
    await db.commit()


async def record_webhook_delivery(
    db: AsyncSession,
    webhook_id: int,
    event_type: str,
    payload: dict,
    status: str,
    response_status: int | None = None,
    response_body: str | None = None,
    error_message: str | None = None,
    attempt_number: int = 1,
) -> WebhookDelivery:
    """Записать попытку доставки webhook."""
    delivery = WebhookDelivery(
        webhook_id=webhook_id,
        event_type=event_type,
        payload=payload,
        status=status,
        response_status=response_status,
        response_body=response_body,
        error_message=error_message,
        attempt_number=attempt_number,
        delivered_at=datetime.now(UTC) if status == 'success' else None,
    )
    db.add(delivery)
    await db.commit()
    await db.refresh(delivery)
    return delivery


async def update_webhook_stats(
    db: AsyncSession,
    webhook: Webhook,
    success: bool,
) -> Webhook:
    """Обновить статистику webhook."""
    if success:
        webhook.success_count += 1
    else:
        webhook.failure_count += 1
    webhook.last_triggered_at = datetime.now(UTC)
    await db.commit()
    await db.refresh(webhook)
    return webhook
