"""Gmail data agent — A2A server using pydantic-ai.

Email access is served from mock data (data/mock_data/emails.py).
"""
import os
from pathlib import Path

from loguru import logger as _log
from pydantic_ai import RunContext

from backend.chanakya.a2a_context import RequestContext, make_metadata_aware_app
from backend.chanakya.base import EnterpriseAgent
from backend.chanakya.config import AGENT_REGISTRY
from data.mock_data.emails import EMAILS
from pylogue.shell import app_factory as create_core_app

_cfg = AGENT_REGISTRY["gmail"]

_GMAIL_AGENT_PROMPT = """\
You are a Gmail data agent for Tata Steel's Enterprise Brain platform.
You have access to the user's real Gmail inbox via the gws CLI.
Answer questions about emails concisely. Always cite the email subject and date.
When calling search_emails, pass short keyword terms only (e.g. 'coking coal'), never full sentences.
Use read_email to fetch the full body of a specific message by ID.
If a tool returns no results, respond immediately with a clear 'nothing found' message. Never retry with alternative queries.
"""

gmail_agent = EnterpriseAgent(
    api_base=os.environ["LITELLM_PROVIDER_BASE_URL"],
    instructions=_GMAIL_AGENT_PROMPT,
    logfire_env="chanakya-alpha",
    service_name="gmail",
    deps_type=RequestContext,
)


@gmail_agent.tool
async def search_emails(ctx: RunContext[RequestContext], query: str, max_results: int = 20) -> str:
    """Search the Gmail inbox using a keyword or Gmail search query.

    Returns a summary table of matching messages (id, from, subject, date).
    Use read_email to fetch the full body of any message.

    Args:
        query:       Gmail search query, e.g. 'coking coal', 'from:boss is:unread'.
        max_results: Maximum number of results to return (default 20).
    """
    _log.debug("search_emails caller={} query={!r}", ctx.deps.user_email, query)
    user = ctx.deps.user_email
    terms = query.lower().split()

    def _matches(msg: dict) -> bool:
        if user and user not in msg.get("recipients_visible_to", []):
            return False
        haystack = " ".join([
            msg.get("subject", ""),
            msg.get("from", ""),
            msg.get("to", ""),
            msg.get("body", ""),
            " ".join(msg.get("labels", [])),
        ]).lower()
        return all(t in haystack for t in terms)

    rows = [m for m in EMAILS if _matches(m)][:max_results]

    if not rows:
        return f"No emails found matching '{query}'."

    lines = ["id | from | subject | date"]
    for msg in rows:
        lines.append(
            f"{msg.get('id', '?')} | {msg.get('from', '?')} | {msg.get('subject', '?')} | {msg.get('date', '?')}"
        )
    return "\n".join(lines)


@gmail_agent.tool
async def read_email(ctx: RunContext[RequestContext], message_id: str) -> str:
    """Read the full body (and key headers) of a single Gmail message by ID.

    Args:
        message_id: The Gmail message ID returned by search_emails.
    """
    _log.debug("read_email caller={} id={!r}", ctx.deps.user_email, message_id)
    user = ctx.deps.user_email
    msg = next((m for m in EMAILS if m["id"] == message_id), None)

    if msg is None:
        return f"No email found with id '{message_id}'."
    if user and user not in msg.get("recipients_visible_to", []):
        return f"Email '{message_id}' is not accessible to {user}."

    return (
        f"From: {msg.get('from', '?')}\n"
        f"To: {msg.get('to', '?')}\n"
        f"Subject: {msg.get('subject', '?')}\n"
        f"Date: {msg.get('date', '?')}\n\n"
        f"{msg.get('body', '').strip()}"
    )


app = make_metadata_aware_app(
    gmail_agent,
    name=_cfg.name,
    description=_cfg.description,
)


@app.on_event("startup")
async def _startup_banner() -> None:
    port = os.environ.get("GMAIL_AGENT_PORT", "8001")
    _log.info("\n  Gmail Agent ready:")
    _log.info("    A2A   → http://0.0.0.0:{}/", port)
    _log.info("    Chat  → http://0.0.0.0:{}/chat", port)
    _log.info("    Card  → http://0.0.0.0:{}/.well-known/agent-card.json", port)
# FastAPI path-strips /chat so pylogue sees / internally.
# Access at: http://localhost:8001/chat
# In Docker, PYLOGUE_DB_PATH=/data/chat_history.db (bind-mounted from ./data/conversation-histories/gmail/).
_PROJECT_ROOT = Path(__file__).parents[3]
_gmail_db_path = os.environ.get(
    "PYLOGUE_DB_PATH",
    str(_PROJECT_ROOT / "data" / "conversation-histories" / "gmail" / "chat_history.db"),
)
Path(_gmail_db_path).parent.mkdir(parents=True, exist_ok=True)


app.mount(
    "/chat",
    create_core_app(
        responder_factory=lambda: gmail_agent,
        hero_title="Gmail Agent",
        hero_subtitle="Search and retrieve Tata Steel emails.",
        db_path=_gmail_db_path,
    ),
)


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(_cfg.module_path, host=_cfg.host, port=_cfg.port, reload=True)
