#!/usr/bin/env python3
"""
Gmail API Skill — Tony's Gmail interface for ohmandd@gmail.com
Uses OAuth2 (token stored at ~/.config/gmail/token.json)
Credentials at ~/.config/gmail/credentials.json

Commands:
  count                  — Unread message count
  urgent                 — Unread messages with urgent keywords (last 7 days)
  search <query>         — Search inbox by Gmail query syntax
  appointments           — Scan for appointment/confirmation emails (last 3 days)
  label <name>           — List messages in a label
  unread [max]           — List recent unread subjects (default 10)
  mark-read <msg_id>     — Mark a message as read
  trash <msg_id>         — Move message to trash
"""

import os, sys, json, base64
from pathlib import Path

CREDS_PATH = Path.home() / ".config/gmail/credentials.json"
TOKEN_PATH = Path.home() / ".config/gmail/token.json"
SCOPES = ["https://www.googleapis.com/auth/gmail.modify"]

def get_service():
    try:
        from google.oauth2.credentials import Credentials
        from google.auth.transport.requests import Request
        from google_auth_oauthlib.flow import InstalledAppFlow
        from googleapiclient.discovery import build
    except ImportError:
        # Try using the venv from youtube-playlists script
        import subprocess
        venv_pip = Path.home() / ".openclaw/workspace/scripts/youtube-playlists/venv/bin/pip"
        if venv_pip.exists():
            subprocess.run([str(venv_pip), "install", "-q",
                           "google-auth", "google-auth-oauthlib", "google-api-python-client"],
                          capture_output=True)
        from google.oauth2.credentials import Credentials
        from google.auth.transport.requests import Request
        from google_auth_oauthlib.flow import InstalledAppFlow
        from googleapiclient.discovery import build

    creds = None
    if TOKEN_PATH.exists():
        creds = Credentials.from_authorized_user_file(str(TOKEN_PATH), SCOPES)
    if not creds or not creds.valid:
        if creds and creds.expired and creds.refresh_token:
            creds.refresh(Request())
            TOKEN_PATH.write_text(creds.to_json())
        else:
            if not CREDS_PATH.exists():
                print("ERROR: No credentials.json found at ~/.config/gmail/credentials.json")
                print("Run: gmail.sh setup")
                sys.exit(1)
            flow = InstalledAppFlow.from_client_secrets_file(str(CREDS_PATH), SCOPES)
            creds = flow.run_local_server(port=0)
            TOKEN_PATH.parent.mkdir(parents=True, exist_ok=True)
            TOKEN_PATH.write_text(creds.to_json())

    return build("gmail", "v1", credentials=creds)


def count_unread(service):
    result = service.users().messages().list(
        userId="me", q="is:unread in:inbox", maxResults=1
    ).execute()
    # Gmail API doesn't return total count directly without pagination
    # Use labels API for accurate count
    label = service.users().labels().get(userId="me", id="INBOX").execute()
    print(label.get("messagesUnread", 0))


def urgent_scan(service):
    query = "is:unread in:inbox newer_than:7d (subject:urgent OR subject:important OR subject:\"action required\" OR subject:\"time sensitive\" OR subject:asap OR subject:immediate)"
    result = service.users().messages().list(
        userId="me", q=query, maxResults=20
    ).execute()
    messages = result.get("messages", [])
    if not messages:
        print("none")
        return
    for msg in messages:
        detail = service.users().messages().get(
            userId="me", id=msg["id"], format="metadata",
            metadataHeaders=["Subject", "From", "Date"]
        ).execute()
        headers = {h["name"]: h["value"] for h in detail["payload"]["headers"]}
        print(f"Subject: {headers.get('Subject', '(no subject)')}")
        print(f"From: {headers.get('From', '')}")
        print(f"Date: {headers.get('Date', '')}")
        print("---")


def search(service, query):
    result = service.users().messages().list(
        userId="me", q=f"in:inbox {query}", maxResults=100
    ).execute()
    messages = result.get("messages", [])
    if not messages:
        print("No matches found")
        return
    for msg in messages:
        detail = service.users().messages().get(
            userId="me", id=msg["id"], format="metadata",
            metadataHeaders=["Subject", "From", "Date"]
        ).execute()
        headers = {h["name"]: h["value"] for h in detail["payload"]["headers"]}
        read = "UNREAD" not in detail.get("labelIds", [])
        print(f"Subject: {headers.get('Subject', '(no subject)')}")
        print(f"From: {headers.get('From', '')}")
        print(f"Date: {headers.get('Date', '')}")
        print(f"Read: {read}")
        print(f"ID: {msg['id']}")
        print("---")


def appointments(service):
    query = "in:inbox newer_than:3d (subject:appointment OR subject:confirmation OR subject:scheduled OR subject:reminder OR subject:booking OR subject:\"your visit\" OR subject:\"lab result\" OR subject:\"test result\")"
    result = service.users().messages().list(
        userId="me", q=query, maxResults=10
    ).execute()
    messages = result.get("messages", [])
    if not messages:
        print("none")
        return
    for msg in messages:
        detail = service.users().messages().get(
            userId="me", id=msg["id"], format="full",
            metadataHeaders=["Subject", "From", "Date", "Message-ID"]
        ).execute()
        headers = {h["name"]: h["value"] for h in detail["payload"]["headers"]}
        # Extract plain text body
        body = ""
        payload = detail.get("payload", {})
        if payload.get("mimeType") == "text/plain":
            data = payload.get("body", {}).get("data", "")
            body = base64.urlsafe_b64decode(data + "==").decode("utf-8", errors="replace")[:500]
        elif "parts" in payload:
            for part in payload["parts"]:
                if part.get("mimeType") == "text/plain":
                    data = part.get("body", {}).get("data", "")
                    body = base64.urlsafe_b64decode(data + "==").decode("utf-8", errors="replace")[:500]
                    break
        print(f"Subject: {headers.get('Subject', '(no subject)')}")
        print(f"From: {headers.get('From', '')}")
        print(f"Date: {headers.get('Date', '')}")
        print(f"MessageID: {headers.get('Message-ID', msg['id'])}")
        print(f"Content: {body.strip()}")
        print("---")


def unread_list(service, max_results=10):
    result = service.users().messages().list(
        userId="me", q="is:unread in:inbox", maxResults=int(max_results)
    ).execute()
    messages = result.get("messages", [])
    if not messages:
        print("No unread messages")
        return
    for msg in messages:
        detail = service.users().messages().get(
            userId="me", id=msg["id"], format="metadata",
            metadataHeaders=["Subject", "From", "Date"]
        ).execute()
        headers = {h["name"]: h["value"] for h in detail["payload"]["headers"]}
        print(f"Subject: {headers.get('Subject', '(no subject)')}")
        print(f"From: {headers.get('From', '')}")
        print(f"Date: {headers.get('Date', '')}")
        print("---")


def mark_read(service, msg_id):
    service.users().messages().modify(
        userId="me", id=msg_id, body={"removeLabelIds": ["UNREAD"]}
    ).execute()
    print(f"Marked as read: {msg_id}")


def trash_message(service, msg_id):
    service.users().messages().trash(userId="me", id=msg_id).execute()
    print(f"Trashed: {msg_id}")


if __name__ == "__main__":
    if len(sys.argv) < 2:
        print(__doc__)
        sys.exit(0)

    cmd = sys.argv[1]

    if cmd == "setup":
        print("Starting OAuth2 setup...")
        get_service()
        print("✅ Auth complete. Token saved to ~/.config/gmail/token.json")
        sys.exit(0)

    svc = get_service()

    if cmd == "count":
        count_unread(svc)
    elif cmd == "urgent":
        urgent_scan(svc)
    elif cmd == "search":
        if len(sys.argv) < 3:
            print("Usage: gmail.py search <query>")
            sys.exit(1)
        search(svc, " ".join(sys.argv[2:]))
    elif cmd == "appointments":
        appointments(svc)
    elif cmd == "unread":
        max_r = sys.argv[2] if len(sys.argv) > 2 else 10
        unread_list(svc, max_r)
    elif cmd == "mark-read":
        mark_read(svc, sys.argv[2])
    elif cmd == "trash":
        trash_message(svc, sys.argv[2])
    else:
        print(f"Unknown command: {cmd}")
        print(__doc__)
        sys.exit(1)

# TONY-APPROVED: 2026-03-01 | sha:c4728a43
