"""Suppression list manager: manual add, CSV/TXT import, search, delete, Clear All,
bulk check. Suppressed addresses are skipped at import AND at send time."""
import csv
import io

from fastapi import APIRouter, Depends, HTTPException, Query, UploadFile
from pydantic import BaseModel, EmailStr
from sqlalchemy import func, select
from sqlalchemy.ext.asyncio import AsyncSession

from app.api.deps import get_current_user, get_db, require_csrf
from app.core.security import log_audit
from app.models import SuppressionEntry, User
from app.services.recipient_service import is_valid_email

router = APIRouter(prefix="/suppression", tags=["suppression"])

REASON_CHOICES = ("unsubscribed", "bounced", "complaint", "manual", "other")


===SER===
def _ser_attempt(a: SendAttempt, cr_id: int = None) -> dict:
    return {
        "id": a.id,
        "campaign_id": a.campaign_id,
        "campaign_recipient_id": cr_id if cr_id is not None else (a.send_job.campaign_recipient_id if a.send_job else None),
        "account_id": a.gmail_account_id,
        "attempt_number": (a.retry_no or 0) + 1,
        "outcome": a.outcome,
        "error_class": a.error_class,
        "error_message": (a.failure_reason or "")[:300],
        "message_id": a.message_id,
        "thread_id": getattr(a, "thread_id", "") or "",
        "method": a.method,
        "subject": (a.subject or "")[:160],
        "template_name": (a.template_name or "")[:160],
        "provider_response": (a.provider_response or "")[:300],
        "created_at": a.created_at.isoformat() if a.created_at else None,
    }


===CONVERT===
@router.post("/convert-pdf")
async def convert_html_to_pdf(template_id: int = Query(..., description="HTML template to render"),
                              db: AsyncSession = Depends(get_db),
                              user: User = Depends(get_current_user),
                              _: None = Depends(require_csrf)):
    """Convert one of the user's saved HTML templates into a real PDF attachment
    using WeasyPrint. The generated PDF is stored and can be attached to campaigns."""
    tpl = await db.get(EmailTemplate, template_id)
    if not tpl or tpl.user_id != user.id:
        raise HTTPException(status_code=404, detail="Template not found")

    problems = validate_html(tpl.body_html)
    if problems.get("errors"):
        raise HTTPException(status_code=400,
                            detail=f"Template has errors: {'; '.join(problems['errors'])}")

    pdf_bytes = await asyncio.get_event_loop().run_in_executor(None, html_to_pdf, tpl.body_html)
    if not pdf_bytes:
        raise HTTPException(status_code=500, detail="PDF rendering failed")

    verdict, reason = att_svc.scan_for_malware(pdf_bytes, "converted.pdf")
    if not verdict:
        raise HTTPException(status_code=500, detail=f"PDF failed safety scan: {reason}")

    base = re.sub(r"\.[^.]+$", "", tpl.name or "attachment") or "attachment"
    fname = f"{base}.pdf"
    stored = att_svc.save_upload(fname, pdf_bytes)
    att = Attachment(
        user_id=user.id,
        name=f"{tpl.name} (PDF)"[:300],
        filename=fname,
        stored_path=stored["stored_path"],
        mime_type="application/pdf",
        size_bytes=len(pdf_bytes),
        kind="pdf",
        description=f"Generated from template '{tpl.name}' via WeasyPrint",
        html_source_template_id=tpl.id,
        file_sha256=hashlib.sha256(pdf_bytes).hexdigest(),
    )
    db.add(att)
    await db.commit()
    await log_audit(db, user.id, "attachment.convert_pdf", "html_template", tpl.id,
                    {"pdf_attachment_id": att.id, "size": len(pdf_bytes)})
    return {"id": att.id, **_serialize(att)}


