# @File: backend/routers/whatsapp_client.py
# @Desc: Client-facing WhatsApp endpoints. Only the chat surface is wired
#        here — conversation list, message thread, send, mark-as-read. All
#        routes require an authenticated DoItEasy user; the backend resolves
#        the client's active subscription internally (no IDs leaked to the
#        browser).
from __future__ import annotations

import logging
from typing import Optional

from core.database import get_db
from dependencies.auth import get_current_user
from fastapi import APIRouter, Depends, HTTPException, Query, status
from pydantic import BaseModel, Field
from schemas.auth import UserResponse
from services.whatsapp.chat import (
    is_valid_phone,
    list_conversations,
    list_messages,
    mark_conversation_read,
    send_outbound_message,
)
from sqlalchemy.ext.asyncio import AsyncSession

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/client/whatsapp", tags=["whatsapp-client"])


class WhatsappSendMessageIn(BaseModel):
    contact_id: Optional[int] = Field(default=None, description="Existing contact id")
    phone_number: Optional[str] = Field(default=None, description="E.164 or local phone")
    body: Optional[str] = Field(default=None, max_length=4096)
    message_type: str = Field(default="text")
    media_url: Optional[str] = Field(default=None, max_length=2048)
    media_mime: Optional[str] = Field(default=None, max_length=64)


@router.get("/conversations")
async def client_list_conversations(
    unread_only: bool = Query(default=False),
    search: Optional[str] = Query(default=None, max_length=128),
    current_user: UserResponse = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> dict:
    """Return chat list for the current user's active WhatsApp subscription."""
    items = await list_conversations(
        db,
        user_id=current_user.id,
        unread_only=unread_only,
        search=search,
    )
    return {"items": items, "total": len(items)}


@router.get("/conversations/{contact_id}/messages")
async def client_list_messages(
    contact_id: int,
    limit: int = Query(default=200, ge=1, le=200),
    before_id: Optional[int] = Query(default=None, ge=1),
    current_user: UserResponse = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> dict:
    items = await list_messages(
        db,
        user_id=current_user.id,
        contact_id=contact_id,
        limit=limit,
        before_id=before_id,
    )
    return {"items": items, "total": len(items)}


@router.post("/conversations/{contact_id}/messages", status_code=status.HTTP_201_CREATED)
async def client_send_message_to_contact(
    contact_id: int,
    payload: WhatsappSendMessageIn,
    current_user: UserResponse = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> dict:
    msg = await send_outbound_message(
        db,
        user_id=current_user.id,
        contact_id=contact_id,
        phone_number=None,
        body=payload.body,
        message_type=payload.message_type,
        media_url=payload.media_url,
        media_mime=payload.media_mime,
    )
    if not msg:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Unable to send message — check an active WhatsApp plan, body/media, and contact status.",
        )
    return msg


@router.post("/messages", status_code=status.HTTP_201_CREATED)
async def client_send_message_new(
    payload: WhatsappSendMessageIn,
    current_user: UserResponse = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> dict:
    """Send to a phone number that may or may not already be a contact."""
    if not payload.contact_id and not payload.phone_number:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Provide either contact_id or phone_number.",
        )
    if payload.phone_number and not is_valid_phone(payload.phone_number):
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Invalid phone number format.",
        )

    msg = await send_outbound_message(
        db,
        user_id=current_user.id,
        contact_id=payload.contact_id,
        phone_number=payload.phone_number,
        body=payload.body,
        message_type=payload.message_type,
        media_url=payload.media_url,
        media_mime=payload.media_mime,
    )
    if not msg:
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail="Unable to send — check an active WhatsApp plan is assigned and the recipient is not opted-out.",
        )
    return msg


@router.post("/conversations/{contact_id}/read")
async def client_mark_conversation_read(
    contact_id: int,
    current_user: UserResponse = Depends(get_current_user),
    db: AsyncSession = Depends(get_db),
) -> dict:
    updated = await mark_conversation_read(
        db, user_id=current_user.id, contact_id=contact_id
    )
    return {"updated": updated}