"""
Mail API — account management and sync endpoints.
"""

import logging
from typing import Optional, List

from fastapi import APIRouter, HTTPException, Query, BackgroundTasks
from pydantic import BaseModel

from .models import AccountTestResult
from .mail_db import (
    create_email_account,
    get_email_accounts,
    get_email_account,
    delete_email_account,
    log_mail_audit,
)
from .credentials import get_credentials_service
from .aggregator import get_mail_aggregator

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/mail", tags=["Mail"])


class AccountCreateRequest(BaseModel):
    """Request to create an email account."""
    email: str
    display_name: str
    account_type: str = "personal"
    imap_host: str
    imap_port: int = 993
    imap_ssl: bool = True
    smtp_host: str
    smtp_port: int = 465
    smtp_ssl: bool = True
    password: str


@router.post("/accounts", response_model=dict)
async def create_account(
    request: AccountCreateRequest,
    user_id: str = Query(..., description="User ID"),
    tenant_id: str = Query(..., description="Tenant ID"),
):
    """Create a new email account."""
    credentials_service = get_credentials_service()

    # Store credentials securely
    vault_path = await credentials_service.store_credentials(
        account_id=f"{user_id}_{request.email}",
        email=request.email,
        password=request.password,
        imap_host=request.imap_host,
        imap_port=request.imap_port,
        smtp_host=request.smtp_host,
        smtp_port=request.smtp_port,
    )

    # Create account in database
    account_id = await create_email_account(
        user_id=user_id,
        tenant_id=tenant_id,
        email=request.email,
        display_name=request.display_name,
        account_type=request.account_type,
        imap_host=request.imap_host,
        imap_port=request.imap_port,
        imap_ssl=request.imap_ssl,
        smtp_host=request.smtp_host,
        smtp_port=request.smtp_port,
        smtp_ssl=request.smtp_ssl,
        vault_path=vault_path,
    )

    if not account_id:
        raise HTTPException(status_code=500, detail="Failed to create account")

    # Log audit
    await log_mail_audit(
        user_id=user_id,
        action="account_created",
        entity_type="account",
        entity_id=account_id,
        details={"email": request.email},
        tenant_id=tenant_id,
    )

    return {"id": account_id, "status": "created"}


@router.get("/accounts", response_model=List[dict])
async def list_accounts(
    user_id: str = Query(..., description="User ID"),
    tenant_id: Optional[str] = Query(None, description="Tenant ID"),
):
    """List all email accounts for a user."""
    accounts = await get_email_accounts(user_id, tenant_id)
    # Remove sensitive fields
    for account in accounts:
        account.pop("vault_path", None)
    return accounts


@router.get("/accounts/{account_id}", response_model=dict)
async def get_account(
    account_id: str,
    user_id: str = Query(..., description="User ID"),
):
    """Get a single email account."""
    account = await get_email_account(account_id, user_id)
    if not account:
        raise HTTPException(status_code=404, detail="Account not found")
    account.pop("vault_path", None)
    return account


@router.delete("/accounts/{account_id}")
async def remove_account(
    account_id: str,
    user_id: str = Query(..., description="User ID"),
):
    """Delete an email account."""
    account = await get_email_account(account_id, user_id)
    if not account:
        raise HTTPException(status_code=404, detail="Account not found")

    # Delete credentials
    credentials_service = get_credentials_service()
    vault_path = account.get("vault_path", "")
    if vault_path:
        await credentials_service.delete_credentials(account_id, vault_path)

    # Delete from database (cascades to emails)
    success = await delete_email_account(account_id, user_id)
    if not success:
        raise HTTPException(status_code=500, detail="Failed to delete account")

    await log_mail_audit(
        user_id=user_id,
        action="account_deleted",
        entity_type="account",
        entity_id=account_id,
    )

    return {"status": "deleted"}


@router.post("/accounts/{account_id}/test", response_model=AccountTestResult)
async def test_account_connection(
    account_id: str,
    user_id: str = Query(..., description="User ID"),
):
    """Test connection for an email account."""
    account = await get_email_account(account_id, user_id)
    if not account:
        raise HTTPException(status_code=404, detail="Account not found")

    # Get credentials
    credentials_service = get_credentials_service()
    vault_path = account.get("vault_path", "")
    creds = await credentials_service.get_credentials(account_id, vault_path)

    if not creds:
        return AccountTestResult(
            success=False,
            error_message="Credentials not found"
        )

    # Test connection
    aggregator = get_mail_aggregator()
    result = await aggregator.test_account_connection(
        imap_host=account["imap_host"],
        imap_port=account["imap_port"],
        imap_ssl=account["imap_ssl"],
        smtp_host=account["smtp_host"],
        smtp_port=account["smtp_port"],
        smtp_ssl=account["smtp_ssl"],
        email_address=creds.email,
        password=creds.password,
    )

    return result


class ConnectionTestRequest(BaseModel):
    """Request to test connection before saving account."""
    email: str
    imap_host: str
    imap_port: int = 993
    imap_ssl: bool = True
    smtp_host: str
    smtp_port: int = 465
    smtp_ssl: bool = True
    password: str


@router.post("/accounts/test-connection", response_model=AccountTestResult)
async def test_connection_before_save(request: ConnectionTestRequest):
    """
    Test IMAP/SMTP connection before saving an account.

    This allows the wizard to verify credentials are correct
    before creating the account in the database.
    """
    aggregator = get_mail_aggregator()

    result = await aggregator.test_account_connection(
        imap_host=request.imap_host,
        imap_port=request.imap_port,
        imap_ssl=request.imap_ssl,
        smtp_host=request.smtp_host,
        smtp_port=request.smtp_port,
        smtp_ssl=request.smtp_ssl,
        email_address=request.email,
        password=request.password,
    )

    return result


@router.post("/accounts/{account_id}/sync")
async def sync_account(
    account_id: str,
    user_id: str = Query(..., description="User ID"),
    max_emails: int = Query(100, ge=1, le=500),
    background_tasks: BackgroundTasks = None,
):
    """Sync emails from an account."""
    aggregator = get_mail_aggregator()

    try:
        new_count, total_count = await aggregator.sync_account(
            account_id=account_id,
            user_id=user_id,
            max_emails=max_emails,
        )

        return {
            "status": "synced",
            "new_emails": new_count,
            "total_emails": total_count,
        }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/sync-all")
async def sync_all_accounts(
    user_id: str = Query(..., description="User ID"),
    tenant_id: Optional[str] = Query(None),
):
    """Sync all email accounts for a user."""
    aggregator = get_mail_aggregator()
    results = await aggregator.sync_all_accounts(user_id, tenant_id)
    return {"status": "synced", "results": results}
