"""Email bot management API routes."""

import logging

from fastapi import APIRouter, Depends, HTTPException, Query, status
from pydantic import BaseModel
from sqlmodel import select
from sqlmodel.ext.asyncio.session import AsyncSession

from ..auth.dependencies import get_current_user
from ..database.engine import get_session
from ..database.models import EmailBot, User
from .helpers import get_owned_entity

_LOGGER = logging.getLogger(__name__)

router = APIRouter(prefix="/api/email-bots", tags=["email-bots"])


class EmailBotCreate(BaseModel):
    name: str
    icon: str = ""
    email: str
    smtp_host: str
    smtp_port: int = 587
    smtp_username: str = ""
    smtp_password: str = ""
    smtp_use_tls: bool = True


class EmailBotUpdate(BaseModel):
    name: str | None = None
    icon: str | None = None
    email: str | None = None
    smtp_host: str | None = None
    smtp_port: int | None = None
    smtp_username: str | None = None
    smtp_password: str | None = None
    smtp_use_tls: bool | None = None


@router.get("")
async def list_email_bots(
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    result = await session.exec(
        select(EmailBot).where(EmailBot.user_id == user.id)
    )
    return [_response(b) for b in result.all()]


@router.post("", status_code=status.HTTP_201_CREATED)
async def create_email_bot(
    body: EmailBotCreate,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    # Verify SMTP connection before saving
    from notify_bridge_core.notifications.email.client import EmailClient, SmtpConfig
    client = EmailClient(SmtpConfig(
        host=body.smtp_host, port=body.smtp_port,
        username=body.smtp_username, password=body.smtp_password,
        from_address=body.email, from_name=body.name,
        use_tls=body.smtp_use_tls,
    ))
    result = await client.verify_connection()
    if not result.get("success"):
        raise HTTPException(status_code=400, detail=f"SMTP connection failed: {result.get('error', 'Unknown error')}")

    bot = EmailBot(user_id=user.id, **body.model_dump())
    session.add(bot)
    await session.commit()
    await session.refresh(bot)
    return _response(bot)


@router.get("/{bot_id}")
async def get_email_bot(
    bot_id: int,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    bot = await _get_user_bot(session, bot_id, user.id)
    return _response(bot)


@router.put("/{bot_id}")
async def update_email_bot(
    bot_id: int,
    body: EmailBotUpdate,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    bot = await _get_user_bot(session, bot_id, user.id)
    updates = body.model_dump(exclude_unset=True)
    # Reject the masked value the GET response returns so the stored password
    # is preserved if the user saves without retyping it.
    if "smtp_password" in updates:
        pw = updates["smtp_password"]
        if isinstance(pw, str) and pw.startswith("***"):
            updates.pop("smtp_password")
    for field, value in updates.items():
        setattr(bot, field, value)
    session.add(bot)
    await session.commit()
    await session.refresh(bot)
    return _response(bot)


@router.delete("/{bot_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_email_bot(
    bot_id: int,
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    from .delete_protection import check_email_bot, raise_if_used
    bot = await _get_user_bot(session, bot_id, user.id)
    raise_if_used(await check_email_bot(session, bot.id), bot.name)
    await session.delete(bot)
    await session.commit()


@router.post("/{bot_id}/test")
async def test_email_bot(
    bot_id: int,
    locale: str = Query("en"),
    user: User = Depends(get_current_user),
    session: AsyncSession = Depends(get_session),
):
    """Send a test email to the bot's own address to verify SMTP connection."""
    bot = await _get_user_bot(session, bot_id, user.id)

    from ..services.notifier import _get_test_message
    msg = _get_test_message(locale, "email")

    from notify_bridge_core.notifications.email.client import EmailClient, SmtpConfig
    client = EmailClient(SmtpConfig(
        host=bot.smtp_host,
        port=bot.smtp_port,
        username=bot.smtp_username,
        password=bot.smtp_password,
        from_address=bot.email,
        from_name=bot.name,
        use_tls=bot.smtp_use_tls,
    ))
    result = await client.send(
        to_email=bot.email,
        subject=f"Notify Bridge — {msg}",
        body_text=msg,
    )
    return result


def _response(bot: EmailBot) -> dict:
    return {
        "id": bot.id,
        "name": bot.name,
        "icon": bot.icon,
        "email": bot.email,
        "smtp_host": bot.smtp_host,
        "smtp_port": bot.smtp_port,
        "smtp_username": bot.smtp_username,
        "smtp_password": "***" if bot.smtp_password else "",
        "smtp_use_tls": bot.smtp_use_tls,
        "created_at": bot.created_at.isoformat(),
    }


async def _get_user_bot(session: AsyncSession, bot_id: int, user_id: int) -> EmailBot:
    return await get_owned_entity(
        session, EmailBot, bot_id, user_id, not_found_msg="Email bot not found",
    )
