import logging
from typing import Optional
from fastapi import APIRouter, Depends, HTTPException, status
from pydantic import BaseModel, EmailStr
from sqlalchemy import select
from sqlalchemy.ext.asyncio import AsyncSession
import aiosmtplib
from email.message import EmailMessage

from database import get_db
from models import AppSettings
from crypto import encrypt_string, decrypt_string
from config import settings as env_settings

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/settings", tags=["settings"])


class SettingsUpdate(BaseModel):
    smtp_host: Optional[str] = None
    smtp_port: int = 587
    smtp_user: Optional[str] = None
    smtp_password: Optional[str] = None
    smtp_from: Optional[str] = None
    alert_emails: Optional[str] = None
    expiry_alert_days: str = "30,7,1"


class SettingsResponse(BaseModel):
    smtp_host: Optional[str] = None
    smtp_port: int = 587
    smtp_user: Optional[str] = None
    smtp_from: Optional[str] = None
    has_smtp_password: bool = False
    alert_emails: Optional[str] = None
    expiry_alert_days: str = "30,7,1"


class TestEmailRequest(BaseModel):
    recipient_email: EmailStr


async def get_or_create_settings(db: AsyncSession) -> AppSettings:
    app_settings = await db.get(AppSettings, 1)
    if not app_settings:
        app_settings = AppSettings(
            id=1,
            smtp_host=env_settings.SMTP_HOST,
            smtp_port=env_settings.SMTP_PORT,
            smtp_user=env_settings.SMTP_USER,
            smtp_password_encrypted=encrypt_string(env_settings.SMTP_PASSWORD) if env_settings.SMTP_PASSWORD else None,
            smtp_from=env_settings.SMTP_FROM,
            alert_emails=env_settings.ALERT_EMAILS,
            expiry_alert_days="30,7,1",
        )
        db.add(app_settings)
        await db.commit()
        await db.refresh(app_settings)
    return app_settings


@router.get("", response_model=SettingsResponse)
async def get_settings(db: AsyncSession = Depends(get_db)):
    """Get application configuration."""
    app_settings = await get_or_create_settings(db)
    return SettingsResponse(
        smtp_host=app_settings.smtp_host,
        smtp_port=app_settings.smtp_port,
        smtp_user=app_settings.smtp_user,
        smtp_from=app_settings.smtp_from,
        has_smtp_password=bool(app_settings.smtp_password_encrypted),
        alert_emails=app_settings.alert_emails,
        expiry_alert_days=app_settings.expiry_alert_days,
    )


@router.put("", response_model=SettingsResponse)
async def update_settings(payload: SettingsUpdate, db: AsyncSession = Depends(get_db)):
    """Update application configuration."""
    app_settings = await get_or_create_settings(db)

    app_settings.smtp_host = payload.smtp_host
    app_settings.smtp_port = payload.smtp_port
    app_settings.smtp_user = payload.smtp_user
    if payload.smtp_password:
        app_settings.smtp_password_encrypted = encrypt_string(payload.smtp_password)
    app_settings.smtp_from = payload.smtp_from
    app_settings.alert_emails = payload.alert_emails
    app_settings.expiry_alert_days = payload.expiry_alert_days

    await db.commit()
    await db.refresh(app_settings)

    return SettingsResponse(
        smtp_host=app_settings.smtp_host,
        smtp_port=app_settings.smtp_port,
        smtp_user=app_settings.smtp_user,
        smtp_from=app_settings.smtp_from,
        has_smtp_password=bool(app_settings.smtp_password_encrypted),
        alert_emails=app_settings.alert_emails,
        expiry_alert_days=app_settings.expiry_alert_days,
    )


@router.post("/test-email")
async def send_test_email(payload: TestEmailRequest, db: AsyncSession = Depends(get_db)):
    """Send a test email using current SMTP configuration."""
    app_settings = await get_or_create_settings(db)

    if not app_settings.smtp_host:
        raise HTTPException(
            status_code=400, detail="SMTP host is not configured. Please save SMTP settings first."
        )

    smtp_password = (
        decrypt_string(app_settings.smtp_password_encrypted)
        if app_settings.smtp_password_encrypted
        else None
    )

    msg = EmailMessage()
    msg["Subject"] = "Domain Platform Test Email"
    msg["From"] = app_settings.smtp_from or app_settings.smtp_user or "noreply@domainplatform.local"
    msg["To"] = payload.recipient_email
    msg.set_content(
        "Hello!\n\nThis is a test email from your Domain Management Platform. "
        "Your SMTP notification system is configured correctly.\n\n"
        "— Domain Management Platform"
    )

    try:
        await aiosmtplib.send(
            msg,
            hostname=app_settings.smtp_host,
            port=app_settings.smtp_port,
            username=app_settings.smtp_user,
            password=smtp_password,
            start_tls=True if app_settings.smtp_port == 587 else False,
            use_tls=True if app_settings.smtp_port == 465 else False,
            timeout=10.0,
        )
        return {"success": True, "message": f"Test email sent successfully to {payload.recipient_email}"}
    except Exception as e:
        logger.error(f"Failed to send test email: {e}")
        raise HTTPException(status_code=500, detail=f"Failed to send test email: {str(e)}")
