TOOL_NAME = "contact_lookup"
TOOL_DESCRIPTION = """Look up a contact's email address by name. Searches Outlook address book (GAL / Contacts) first, then falls back to recent sent emails."""
TOOL_ARGS = '{"name": {"type": "string", "description": "Full or partial name of the contact to look up"}}'

import sys
from tools._std import tool_ok, tool_error

def _outlook_resolve(name: str) -> list[dict]:
    """Try to resolve a name via Outlook COM (GAL + local contacts)."""
    if sys.platform != "win32":
        return []
    try:
        import win32com.client
        outlook = win32com.client.Dispatch("Outlook.Application")
        ns = outlook.GetNamespace("MAPI")
        recip = ns.CreateRecipient(name)
        recip.Resolve()
        if recip.Resolved:
            ae = recip.AddressEntry
            results = []
            if ae.AddressEntryUserType == 0:  # ExchangeUser
                eu = ae.GetExchangeUser()
                if eu:
                    results.append({
                        "name": eu.Name,
                        "email": eu.PrimarySmtpAddress,
                        "source": "Exchange GAL",
                    })
            if not results:
                email_addr = ae.Address
                if "@" in str(email_addr or ""):
                    results.append({
                        "name": ae.Name,
                        "email": email_addr,
                        "source": "Outlook Contacts",
                    })
            return results
    except Exception as e:
        print(f"[contact_lookup] Outlook resolve error: {e}")
    return []


def _outlook_sent_search(name: str) -> list[dict]:
    """Fallback: search recent sent items for a matching recipient name."""
    if sys.platform != "win32":
        return []
    try:
        import win32com.client
        outlook = win32com.client.Dispatch("Outlook.Application")
        ns = outlook.GetNamespace("MAPI")
        sent = ns.GetDefaultFolder(5)  # olFolderSentMail
        items = sent.Items
        items.Sort("[SentOn]", True)
        name_lower = name.lower()
        found = {}
        count = 0
        for item in items:
            count += 1
            if count > 200:
                break
            try:
                for recip in item.Recipients:
                    rname = str(getattr(recip, "Name", "") or "")
                    if name_lower in rname.lower():
                        ae = recip.AddressEntry
                        email_addr = None
                        if ae.AddressEntryUserType == 0:
                            eu = ae.GetExchangeUser()
                            if eu:
                                email_addr = eu.PrimarySmtpAddress
                        if not email_addr:
                            email_addr = ae.Address
                        if email_addr and "@" in str(email_addr) and email_addr not in found:
                            found[email_addr] = {
                                "name": rname,
                                "email": email_addr,
                                "source": "Sent Items",
                            }
            except Exception:
                continue
        return list(found.values())
    except Exception as e:
        print(f"[contact_lookup] Sent search error: {e}")
        return []


def run(args: dict) -> str:
    name = (args.get("name") or "").strip()
    if not name:
        return tool_error("A contact name is required.")

    results = _outlook_resolve(name)
    if not results:
        results = _outlook_sent_search(name)

    if not results:
        return tool_error(f"No contact found for '{name}'. Try a different spelling or search your inbox manually.")

    return tool_ok(
        {"contacts": results, "count": len(results)},
        "\n".join(f"{c['name']} — {c['email']} ({c['source']})" for c in results),
    )
