#!/usr/bin/env python3
"""Gmail contact extractor for Clawdbot - scans emails and extracts unique contacts."""

import subprocess
import json
import re
import requests
from collections import defaultdict
from datetime import datetime

# Configuration
NOTION_API_KEY = "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"
CONTACTS_INBOX_DB = "2f0330c2-8646-814e-af5a-c7d3b36030ef"
PEOPLE_DIRECTORY_DB = "142acbed-9e19-48e0-911f-2fc6513b564d"

# Patterns to filter out automated emails
AUTOMATED_PATTERNS = [
    r'noreply|no-reply|no_reply',
    r'notifications?@',
    r'newsletter',
    r'donotreply',
    r'mailer-daemon',
    r'postmaster@',
    r'support@',
    r'info@news\.',
    r'hello@news\.',
    r'updates@',
    r'alerts?@',
    r'billing@',
    r'receipts?@',
    r'invoice',
    r'marketing@',
    r'promo@',
    r'sales@',
    r'team@email\.',
    r'digest@',
    r'@e\..*\.com',  # marketing emails like @e.cos.com
    r'@mail\..*\.com',
    r'@info\..*\.com',
    r'advertise-',
    r'security@updates',
    r'comments-noreply',
    r'via (google|figma|linkedin)',
]

# Known newsletter/automated senders
AUTOMATED_SENDERS = [
    'meta for business',
    'anthropic, pbc',
    'audible.com',
    'audible',
    'linear',
    'github',
    'google',
    'stripe',
    'namecheap',
    'american express',
    'amex',
    'classdojo',
    'adobe',
    'pixel surplus',
    'nyt cooking',
    'the defiant',
    'vanguard',
    'easypark',
    'behance',
    'homeexchange',
    'retrosupply',
    'cos',
    'awwwards',
    'brave search',
    'tl;dv',
    'rehunt',
    'lovable',
    'beckett simonon',
    'granvine',
    'buraca roasters',
    'merchery',
    'vml intelligence',
    'mockup.maison',
    'userlist',
    'claude team',
    'anthropic team',
    'the new school',
    'kindred',
    'atlantax',
    "new york's 529",
]

def is_automated_email(from_field):
    """Check if email is from an automated sender."""
    from_lower = from_field.lower()
    
    # Check patterns
    for pattern in AUTOMATED_PATTERNS:
        if re.search(pattern, from_lower, re.IGNORECASE):
            return True
    
    # Check known senders
    for sender in AUTOMATED_SENDERS:
        if sender in from_lower:
            return True
    
    return False

def extract_email_and_name(from_field):
    """Extract name and email from a From field."""
    # Pattern: "Name" <email@domain.com> or Name <email@domain.com> or just email@domain.com
    match = re.match(r'^"?([^"<]+)"?\s*<([^>]+)>$', from_field.strip())
    if match:
        name = match.group(1).strip().strip('"')
        email = match.group(2).strip().lower()
        return name, email
    
    # Just an email
    match = re.match(r'^([a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})$', from_field.strip())
    if match:
        email = match.group(1).lower()
        name = email.split('@')[0].replace('.', ' ').replace('_', ' ').title()
        return name, email
    
    return None, None

def get_existing_contacts():
    """Get existing contacts from Notion People Directory."""
    contacts = set()
    headers = {
        "Authorization": f"Bearer {NOTION_API_KEY}",
        "Notion-Version": "2022-06-28",
        "Content-Type": "application/json"
    }
    
    has_more = True
    start_cursor = None
    
    while has_more:
        payload = {"page_size": 100}
        if start_cursor:
            payload["start_cursor"] = start_cursor
        
        resp = requests.post(
            f"https://api.notion.com/v1/databases/{PEOPLE_DIRECTORY_DB}/query",
            headers=headers,
            json=payload
        )
        
        if resp.status_code != 200:
            print(f"Error fetching People Directory: {resp.text}")
            break
        
        data = resp.json()
        
        for result in data.get("results", []):
            props = result.get("properties", {})
            # Try to get name
            if "Name" in props and props["Name"].get("title"):
                for t in props["Name"]["title"]:
                    if "text" in t:
                        contacts.add(t["text"]["content"].lower())
            # Try to get email
            if "Email" in props and props["Email"].get("email"):
                contacts.add(props["Email"]["email"].lower())
        
        has_more = data.get("has_more", False)
        start_cursor = data.get("next_cursor")
    
    return contacts

def get_inbox_contacts():
    """Get contacts already in Contacts Inbox."""
    contacts = set()
    headers = {
        "Authorization": f"Bearer {NOTION_API_KEY}",
        "Notion-Version": "2022-06-28",
        "Content-Type": "application/json"
    }
    
    has_more = True
    start_cursor = None
    
    while has_more:
        payload = {"page_size": 100}
        if start_cursor:
            payload["start_cursor"] = start_cursor
        
        resp = requests.post(
            f"https://api.notion.com/v1/databases/{CONTACTS_INBOX_DB}/query",
            headers=headers,
            json=payload
        )
        
        if resp.status_code != 200:
            print(f"Error fetching Contacts Inbox: {resp.text}")
            break
        
        data = resp.json()
        
        for result in data.get("results", []):
            props = result.get("properties", {})
            if "Name" in props and props["Name"].get("title"):
                for t in props["Name"]["title"]:
                    if "text" in t:
                        contacts.add(t["text"]["content"].lower())
            if "Email" in props:
                email_prop = props["Email"]
                if email_prop.get("email"):
                    contacts.add(email_prop["email"].lower())
                elif email_prop.get("rich_text"):
                    for rt in email_prop["rich_text"]:
                        if "text" in rt:
                            contacts.add(rt["text"]["content"].lower())
        
        has_more = data.get("has_more", False)
        start_cursor = data.get("next_cursor")
    
    return contacts

def add_contact_to_notion(name, email, count, context):
    """Add a contact to the Notion Contacts Inbox."""
    headers = {
        "Authorization": f"Bearer {NOTION_API_KEY}",
        "Notion-Version": "2022-06-28",
        "Content-Type": "application/json"
    }
    
    # Build properties - need to match the actual database schema
    properties = {
        "Name": {
            "title": [{"text": {"content": name}}]
        }
    }
    
    # Try to add other fields if they exist
    payload = {
        "parent": {"database_id": CONTACTS_INBOX_DB},
        "properties": properties
    }
    
    resp = requests.post(
        "https://api.notion.com/v1/pages",
        headers=headers,
        json=payload
    )
    
    if resp.status_code != 200:
        # Try to get database schema
        schema_resp = requests.get(
            f"https://api.notion.com/v1/databases/{CONTACTS_INBOX_DB}",
            headers=headers
        )
        if schema_resp.status_code == 200:
            schema = schema_resp.json()
            print(f"Database schema: {json.dumps(schema.get('properties', {}), indent=2)}")
        print(f"Error adding contact {name}: {resp.text}")
        return False
    
    return True

def scan_emails_batch(query, limit=50):
    """Scan a batch of emails and return contacts."""
    result = subprocess.run(
        ["/Users/assafdagan/.clawdbot/skills/gmail/gmail", "search", query, "-n", str(limit), "-v"],
        capture_output=True,
        text=True
    )
    
    contacts = defaultdict(lambda: {"count": 0, "subjects": []})
    lines = result.stdout.split('\n')
    
    current_from = None
    current_subject = None
    
    for line in lines:
        # Match email line: ● [date] From <email> | Subject
        match = re.match(r'^[●\s]\s*\[([^\]]+)\]\s+(.+?)\s*\|\s*(.*)$', line.strip())
        if match:
            date_str = match.group(1)
            from_field = match.group(2).strip()
            subject = match.group(3).strip()
            
            # Check if we've gone past July 2025
            try:
                date = datetime.strptime(date_str, '%Y-%m-%d %H:%M')
                if date.year < 2025 or (date.year == 2025 and date.month < 7):
                    return contacts, True  # Signal we've reached the cutoff
            except:
                pass
            
            if not is_automated_email(from_field):
                name, email = extract_email_and_name(from_field)
                if email and not email.endswith('@gmail.com') or (email and 'assaf' not in email.lower()):
                    # Skip own emails
                    if email and 'assafdagan' not in email.lower():
                        contacts[email]["name"] = name
                        contacts[email]["count"] += 1
                        if subject and len(contacts[email]["subjects"]) < 3:
                            contacts[email]["subjects"].append(subject[:50])
    
    return contacts, False

def main():
    print("=== Gmail Contact Scanner ===\n")
    
    # Get existing contacts
    print("Fetching existing contacts from Notion People Directory...")
    existing = get_existing_contacts()
    print(f"Found {len(existing)} existing contacts in People Directory")
    
    print("Fetching contacts already in Inbox...")
    inbox_existing = get_inbox_contacts()
    print(f"Found {len(inbox_existing)} contacts already in Contacts Inbox")
    
    all_existing = existing | inbox_existing
    
    # Scan emails in batches
    all_contacts = defaultdict(lambda: {"count": 0, "subjects": [], "name": ""})
    reached_cutoff = False
    batch = 0
    
    # Use different date ranges to get more coverage
    queries = [
        "after:2025/12/01",
        "after:2025/11/01 before:2025/12/01",
        "after:2025/10/01 before:2025/11/01",
        "after:2025/09/01 before:2025/10/01",
        "after:2025/08/01 before:2025/09/01",
        "after:2025/07/01 before:2025/08/01",
    ]
    
    for query in queries:
        if reached_cutoff:
            break
        
        print(f"\nScanning: {query}")
        contacts, cutoff = scan_emails_batch(query, limit=100)
        
        for email, data in contacts.items():
            all_contacts[email]["count"] += data["count"]
            all_contacts[email]["name"] = data.get("name", all_contacts[email]["name"])
            all_contacts[email]["subjects"].extend(data.get("subjects", []))
        
        print(f"  Found {len(contacts)} contacts in this batch")
        
        if cutoff:
            reached_cutoff = True
    
    # Filter out existing contacts
    new_contacts = {
        email: data for email, data in all_contacts.items()
        if email.lower() not in all_existing and data.get("name", "").lower() not in all_existing
    }
    
    print(f"\n=== Results ===")
    print(f"Total unique contacts found: {len(all_contacts)}")
    print(f"New contacts (not in Notion): {len(new_contacts)}")
    
    # Sort by email count
    sorted_contacts = sorted(new_contacts.items(), key=lambda x: x[1]["count"], reverse=True)
    
    print("\n--- New Contacts (sorted by frequency) ---")
    for email, data in sorted_contacts[:30]:
        context = "; ".join(data["subjects"][:2]) if data["subjects"] else ""
        print(f"{data['name']:30} | {email:40} | {data['count']:3} emails | {context[:40]}")
    
    # Save results to file
    results = {
        "total_found": len(all_contacts),
        "new_contacts": len(new_contacts),
        "contacts": [
            {
                "name": data["name"],
                "email": email,
                "count": data["count"],
                "context": "; ".join(data["subjects"][:3])
            }
            for email, data in sorted_contacts
        ]
    }
    
    with open("/Users/assafdagan/clawd/gmail_contacts_results.json", "w") as f:
        json.dump(results, f, indent=2)
    
    print(f"\nResults saved to gmail_contacts_results.json")
    print(f"Ready to add {len(new_contacts)} contacts to Notion Contacts Inbox")

if __name__ == "__main__":
    main()
