"""
Contact catalog (port authorities + aid owners) + alert report log.
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from pydantic import BaseModel
from sqlalchemy.orm import Session
from typing import Optional
import uuid

from database import get_db
from models.contact import Contact, AlertReport
from models.aid import Aid
from models.user import User
from routers.auth import get_current_user, require_admin
from services import notifier

router = APIRouter(tags=["contacts"])


class ContactIn(BaseModel):
    name:              str
    role:              str                    # PORT_AUTHORITY | OWNER
    email:             Optional[str] = None
    phone:             Optional[str] = None
    whatsapp:          Optional[str] = None
    port_name:         Optional[str] = None
    company_name:      Optional[str] = None
    preferred_channel: str = "EMAIL"
    notes:             Optional[str] = None


def _row_to_dict(c: Contact) -> dict:
    return {col.name: getattr(c, col.name) for col in c.__table__.columns}


# ── Contacts CRUD (SUPERADMIN only) ───────────────────────────────────────
@router.get("/contacts/")
def list_contacts(db: Session = Depends(get_db)):
    return [_row_to_dict(c) for c in db.query(Contact).order_by(Contact.role, Contact.name).all()]


@router.post("/contacts/")
def create_contact(data: ContactIn, db: Session = Depends(get_db),
                   current_user: User = Depends(require_admin)):
    if data.role not in ("PORT_AUTHORITY", "OWNER"):
        raise HTTPException(400, "role must be PORT_AUTHORITY or OWNER")
    if data.preferred_channel not in ("EMAIL", "SMS", "WHATSAPP"):
        raise HTTPException(400, "preferred_channel must be EMAIL, SMS or WHATSAPP")
    c = Contact(id=str(uuid.uuid4()), **data.model_dump())
    db.add(c); db.commit(); db.refresh(c)
    return _row_to_dict(c)


@router.put("/contacts/{contact_id}")
def update_contact(contact_id: str, data: ContactIn, db: Session = Depends(get_db),
                   current_user: User = Depends(require_admin)):
    c = db.query(Contact).filter(Contact.id == contact_id).first()
    if not c: raise HTTPException(404, "Contact not found")
    for k, v in data.model_dump().items():
        setattr(c, k, v)
    db.commit(); db.refresh(c)
    return _row_to_dict(c)


@router.delete("/contacts/{contact_id}")
def delete_contact(contact_id: str, db: Session = Depends(get_db),
                   current_user: User = Depends(require_admin)):
    db.query(Contact).filter(Contact.id == contact_id).delete()
    db.commit()
    return {"deleted": contact_id}


# ── Resolve recipients for a given aid ────────────────────────────────────
@router.get("/alerts/resolve-recipients")
def resolve_recipients(aid_id: Optional[str] = None, mmsi: Optional[str] = None,
                       db: Session = Depends(get_db)):
    """For a given aid (by id or mmsi), return port authority + owner contacts."""
    aid = None
    if aid_id:
        aid = db.query(Aid).filter(Aid.id == aid_id).first()
    if aid is None and mmsi:
        aid = db.query(Aid).filter(Aid.mmsi == mmsi).first()
    if aid is None:
        return {"aid": None, "recipients": []}

    recipients = []
    if aid.puerto_responsable:
        for c in db.query(Contact).filter(
            Contact.role == "PORT_AUTHORITY",
            Contact.port_name == aid.puerto_responsable
        ).all():
            recipients.append(_row_to_dict(c))
    if aid.empresa_responsable:
        for c in db.query(Contact).filter(
            Contact.role == "OWNER",
            Contact.company_name == aid.empresa_responsable
        ).all():
            recipients.append(_row_to_dict(c))

    return {
        "aid": {
            "id": aid.id, "nombre": aid.nombre, "mmsi": aid.mmsi,
            "puerto_responsable": aid.puerto_responsable,
            "empresa_responsable": aid.empresa_responsable,
        },
        "recipients": recipients,
    }


# ── Log a report (audit trail) ────────────────────────────────────────────
class ReportIn(BaseModel):
    alert_id:      Optional[str] = None
    alert_tipo:    Optional[str] = None
    alert_subtipo: Optional[str] = None
    aid_id:        Optional[str] = None
    aid_nombre:    Optional[str] = None
    mmsi:          Optional[str] = None
    contact_id:    Optional[str] = None
    contact_name:  Optional[str] = None
    channel:       str   # EMAIL | SMS | WHATSAPP
    recipient:     str
    message:       Optional[str] = None


@router.post("/alerts/report")
def log_report(data: ReportIn, db: Session = Depends(get_db),
               current_user: User = Depends(get_current_user)):
    """Log a report row AND, when channel=EMAIL and SMTP is configured,
    actually send the email through the operator's SMTP account.
    The frontend can then skip opening mailto:."""
    smtp_sent = False
    smtp_detail = None
    if data.channel == "EMAIL" and notifier.smtp_configured() and data.recipient:
        subject = f"[AidsMonitoring] {data.alert_tipo or 'Alert'} — {data.aid_nombre or data.aid_id or ''}"
        smtp_sent, smtp_detail = notifier.send_email(data.recipient, subject, data.message or "")

    rep = AlertReport(
        id=str(uuid.uuid4()),
        reported_by=current_user.username,
        **data.model_dump(),
    )
    db.add(rep); db.commit()
    return {
        "ok": True,
        "id": rep.id,
        "smtp_sent": smtp_sent,
        "smtp_detail": smtp_detail,
        "smtp_configured": notifier.smtp_configured(),
    }


@router.get("/alerts/reports")
def list_reports(alert_id: Optional[str] = Query(None),
                 limit: int = 200,
                 db: Session = Depends(get_db),
                 current_user: User = Depends(get_current_user)):
    q = db.query(AlertReport)
    if alert_id:
        q = q.filter(AlertReport.alert_id == alert_id)
    rows = q.order_by(AlertReport.reported_at.desc()).limit(limit).all()
    return [{col.name: getattr(r, col.name) for col in r.__table__.columns} for r in rows]
