"""Twilio WhatsApp + SMS messaging — for invoice reminders and notifications."""
import os
import logging
from typing import Optional
from fastapi import APIRouter, HTTPException, Depends, Request
from pydantic import BaseModel, Field

from auth import get_current_user

logger = logging.getLogger("rm-regal.messaging")

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


class SendIn(BaseModel):
    to: str = Field(..., description="E.164 phone number, e.g. +919049202606")
    body: str
    invoice_id: Optional[str] = None  # for activity log linkage


def _check_creds() -> tuple[str, str]:
    sid = os.environ.get("TWILIO_ACCOUNT_SID", "").strip()
    token = os.environ.get("TWILIO_AUTH_TOKEN", "").strip()
    if not sid or not token:
        raise HTTPException(
            400,
            "Twilio not configured. Add TWILIO_ACCOUNT_SID and TWILIO_AUTH_TOKEN to backend .env and restart.",
        )
    return sid, token


def _normalize_phone(num: str) -> str:
    n = (num or "").strip().replace(" ", "").replace("-", "")
    if not n:
        raise HTTPException(400, "Recipient phone number is required")
    if not n.startswith("+"):
        # default to India country code if 10 digits
        if len(n) == 10 and n.isdigit():
            n = "+91" + n
        else:
            n = "+" + n
    return n


async def _send_twilio(channel: str, payload: SendIn, user: dict, db) -> dict:
    sid, token = _check_creds()
    # Determine sender: either a Messaging Service SID (starts with "MG") or a specific number.
    if channel == "whatsapp":
        from_num = os.environ.get("TWILIO_WHATSAPP_FROM", "").strip()
        if not from_num:
            raise HTTPException(400, "TWILIO_WHATSAPP_FROM env var is missing.")
        to_addr = f"whatsapp:{_normalize_phone(payload.to)}"
        if from_num.startswith("MG"):
            sender_kwargs = {"messaging_service_sid": from_num}
        else:
            from_addr = from_num if from_num.startswith("whatsapp:") else f"whatsapp:{from_num}"
            sender_kwargs = {"from_": from_addr}
    else:
        from_num = os.environ.get("TWILIO_SMS_FROM", "").strip()
        if not from_num:
            raise HTTPException(400, "TWILIO_SMS_FROM env var is missing.")
        to_addr = _normalize_phone(payload.to)
        if from_num.startswith("MG"):
            sender_kwargs = {"messaging_service_sid": from_num}
        else:
            sender_kwargs = {"from_": from_num}

    try:
        from twilio.rest import Client
        client = Client(sid, token)
        msg = client.messages.create(to=to_addr, body=payload.body, **sender_kwargs)
    except Exception as e:
        logger.exception("Twilio send failed")
        raise HTTPException(502, f"Twilio error: {e}")

    # log activity
    try:
        from datetime import datetime, timezone
        await db.activity_logs.insert_one({
            "user_id": user["id"],
            "user_email": user["email"],
            "action": "send",
            "entity": channel,
            "entity_id": payload.invoice_id,
            "meta": {"to": to_addr, "sid": msg.sid, "status": msg.status},
            "timestamp": datetime.now(timezone.utc).isoformat(),
        })
    except Exception:
        pass

    return {"ok": True, "sid": msg.sid, "status": msg.status, "to": to_addr}


@router.post("/whatsapp")
async def send_whatsapp(payload: SendIn, request: Request, user=Depends(get_current_user)):
    return await _send_twilio("whatsapp", payload, user, request.app.state.db)


@router.post("/sms")
async def send_sms(payload: SendIn, request: Request, user=Depends(get_current_user)):
    return await _send_twilio("sms", payload, user, request.app.state.db)


@router.get("/status")
async def status(user=Depends(get_current_user)):
    sid = os.environ.get("TWILIO_ACCOUNT_SID", "").strip()
    return {
        "configured": bool(sid and os.environ.get("TWILIO_AUTH_TOKEN", "").strip()),
        "whatsapp_from": os.environ.get("TWILIO_WHATSAPP_FROM", ""),
        "sms_from": os.environ.get("TWILIO_SMS_FROM", ""),
    }
