"""Notification service — email (SMTP) and webhook dispatch."""

import json
import smtplib
from email.mime.text import MIMEText
from datetime import datetime

import httpx
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession

from app.config import settings
from app.models.models import Incident, NotificationLog, Subscriber


async def send_email_notification(
    to_email: str,
    subject: str,
    body: str,
) -> bool:
    """Send an email notification via SMTP. Returns True if successful."""
    if not settings.smtp_host:
        return False

    msg = MIMEText(body, "html")
    msg["Subject"] = subject
    msg["From"] = settings.smtp_from
    msg["To"] = to_email

    try:
        with smtplib.SMTP(settings.smtp_host, settings.smtp_port) as server:
            if settings.smtp_user:
                server.starttls()
                server.login(settings.smtp_user, settings.smtp_pass)
            server.send_message(msg)
        return True
    except Exception:
        return False


async def send_webhook_notification(
    payload: dict,
) -> bool:
    """Send a webhook POST notification. Returns True if successful."""
    if not settings.webhook_notify_url:
        return False

    try:
        async with httpx.AsyncClient() as client:
            response = await client.post(
                settings.webhook_notify_url,
                json=payload,
                timeout=10.0,
            )
            return response.status_code < 400
    except Exception:
        return False


async def notify_subscribers(
    incident: Incident,
    db: AsyncSession,
) -> int:
    """Notify all confirmed subscribers about an incident update. Returns count notified."""
    result = await db.execute(
        select(Subscriber).where(Subscriber.is_confirmed == True)  # noqa: E712
    )
    subscribers = result.scalars().all()

    notified = 0
    subject = f"[{incident.severity.upper()}] {incident.title}"

    for subscriber in subscribers:
        # Email notification
        email_sent = await send_email_notification(
            to_email=subscriber.email,
            subject=subject,
            body=f"<p>{incident.title}</p><p>Status: {incident.status}</p>",
        )
        if email_sent:
            log = NotificationLog(
                incident_id=incident.id,
                subscriber_id=subscriber.id,
                channel="email",
                status="sent",
            )
            db.add(log)
            notified += 1

        # Webhook notification
        webhook_sent = await send_webhook_notification(
            payload={
                "incident_id": incident.id,
                "title": incident.title,
                "status": incident.status,
                "severity": incident.severity,
                "started_at": incident.started_at.isoformat() if incident.started_at else None,
            }
        )
        if webhook_sent:
            log = NotificationLog(
                incident_id=incident.id,
                subscriber_id=subscriber.id,
                channel="webhook",
                status="sent",
            )
            db.add(log)

    await db.flush()
    return notified