"""
Inbox triage: a constrained agentic workflow.

What “agent” means here
-----------------------
This script is a loop with a short, fixed menu of tools. For each inbox
message it:

  1. predicts a label with the saved sklearn model (classify)
  2. chooses the next tools with if/elif (not a chatbot, not “AI deciding”)
  3. writes a log line
  4. moves to the next message

It stops when the inbox list is finished. It does not browse the web,
does not call an LLM, and does not invent new tools. That is an agentic
workflow (steps + tools + a stop), not autonomous intelligence.
"""

from __future__ import annotations

import json
from pathlib import Path

from tools import (
    classify,
    draft_reply,
    lookup_policy,
    make_log_record,
    message_text,
    write_log,
)

HERE = Path(__file__).resolve().parent
INBOX_PATH = HERE / "data" / "inbox.json"
LOG_PATH = HERE / "logs" / "agent_log.jsonl"


def load_inbox(path: Path = INBOX_PATH) -> list[dict]:
    if not path.exists():
        raise FileNotFoundError(
            f"Missing {path}. Run: python generate_data.py"
        )
    rows = json.loads(path.read_text(encoding="utf-8"))
    if not isinstance(rows, list):
        raise ValueError("inbox.json must be a list of messages")
    return rows


def choose_tools(label: str, message: dict) -> tuple[str, str | None, list[str]]:
    """
    Fixed tool choice. The label picks a branch; the branch lists the tools.

    Every branch looks up a local policy and writes a log. Only some
    branches draft a reply.
    """
    tools_used = ["classify"]

    if label == "password_reset":
        policy = lookup_policy("password_reset")
        tools_used.append("lookup_policy")
        reply = draft_reply("password_reset", message)
        tools_used.append("draft_reply")
    elif label == "billing":
        policy = lookup_policy("billing")
        tools_used.append("lookup_policy")
        reply = draft_reply("billing", message)
        tools_used.append("draft_reply")
    elif label == "shipping":
        policy = lookup_policy("shipping")
        tools_used.append("lookup_policy")
        reply = draft_reply("shipping", message)
        tools_used.append("draft_reply")
    elif label == "spam":
        policy = lookup_policy("spam")
        tools_used.append("lookup_policy")
        reply = None
    else:
        policy = lookup_policy("unknown")
        tools_used.append("lookup_policy")
        reply = None

    return policy, reply, tools_used


def handle_message(message: dict, label: str, log_path: Path = LOG_PATH) -> dict:
    policy, reply, tools_used = choose_tools(label, message)
    tools_used = list(tools_used) + ["write_log"]
    record = make_log_record(message, label, policy, reply, tools_used)
    write_log(record, log_path=log_path)
    return record


def run_agent(
    inbox_path: Path = INBOX_PATH,
    log_path: Path = LOG_PATH,
    verbose: bool = True,
) -> list[dict]:
    inbox = load_inbox(inbox_path)
    if verbose:
        print("Inbox triage agent")
        print(
            "This is a constrained agentic workflow: a loop, four tools, "
            "if/elif tool choice, and a hard stop. It is not autonomous intelligence."
        )
        print(f"Inbox size: {len(inbox)}. The loop stops after the last message.")
        print()

    results = []
    for index, message in enumerate(inbox, start=1):
        text = message_text(message)
        label = classify(text)
        record = handle_message(message, label, log_path=log_path)
        results.append(record)

        if not verbose:
            continue
        print(f"--- Message {index}: {message.get('id', '?')} ---")
        print(f"Subject: {message.get('subject', '')}")
        print(f"Predicted label: {label}")
        print(f"Tools used: {', '.join(record['tools_used'])}")
        print(f"Policy: {record['policy']}")
        if record["reply"]:
            print("Draft reply:")
            print(record["reply"])
        else:
            print("Draft reply: (none — do not email the sender)")
        print(f"Logged to {log_path}")
        print()

    if verbose:
        print(
            "Stop: every inbox message was processed once. "
            "No more tools will run."
        )
    return results


def main() -> None:
    run_agent()


if __name__ == "__main__":
    main()
