TOOL_NAME = "email_triage"
TOOL_DESCRIPTION = """Automated email triage system that retrieves unread emails from Gmail and/or Outlook, analyzes content, and categorizes them as urgent (spoed), action needed (actie), or informational (informatief). Returns a prioritized summary with sender, subject, category, and priority score."""
TOOL_ARGS = '{"source": {"type": "string", "enum": ["gmail", "outlook", "both"], "default": "both", "description": "Email source to check"}, "max_emails": {"type": "integer", "default": 50, "description": "Maximum number of unread emails to retrieve per source"}, "days_back": {"type": "integer", "default": 1, "description": "Only check emails from last N days"}, "output_format": {"type": "string", "enum": ["summary", "detailed", "json"], "default": "summary", "description": "Output format"}}'

import imaplib
import email
import re
import json
from datetime import datetime, timedelta
from typing import List, Dict, Any
import warnings
from tools._std import tool_ok, tool_error

def run(args: dict) -> str:
    """
    Email triage system - retrieves and categorizes unread emails.
    Categories: urgent (spoed), actie (action needed), informatief (informational)
    """
    source = args.get('source', 'both')
    max_emails = args.get('max_emails', 50)
    days_back = args.get('days_back', 1)
    output_format = args.get('output_format', 'summary')
    
    results = {
        'timestamp': datetime.now().isoformat(),
        'sources_checked': [],
        'emails': [],
        'summary': {
            'urgent': 0,
            'actie': 0,
            'informatief': 0,
            'total': 0
        }
    }
    
    # Try Outlook
    if source in ['outlook', 'both']:
        try:
            outlook_emails = _get_outlook_unread(max_emails, days_back)
            results['sources_checked'].append('outlook')
            for email_data in outlook_emails:
                categorized = _categorize_email(email_data)
                results['emails'].append(categorized)
                results['summary'][categorized['category']] += 1
                results['summary']['total'] += 1
        except Exception as e:
            results['outlook_error'] = str(e)
    
    # Try Gmail
    if source in ['gmail', 'both']:
        try:
            gmail_emails = _get_gmail_unread(max_emails, days_back)
            results['sources_checked'].append('gmail')
            for email_data in gmail_emails:
                categorized = _categorize_email(email_data)
                results['emails'].append(categorized)
                results['summary'][categorized['category']] += 1
                results['summary']['total'] += 1
        except Exception as e:
            results['gmail_error'] = str(e)
    
    # Sort by priority (urgent first, then by priority score)
    results['emails'].sort(key=lambda x: (
        0 if x['category'] == 'urgent' else (1 if x['category'] == 'actie' else 2),
        -x['priority_score']
    ))
    
    return _format_output(results, output_format)


def _get_outlook_unread(max_emails: int, days_back: int) -> List[Dict]:
    """Retrieve unread emails from Outlook using COM interface."""
    emails = []
    try:
        import pythoncom
        import win32com.client
        pythoncom.CoInitialize()
        
        outlook = win32com.client.Dispatch('Outlook.Application')
        namespace = outlook.GetNamespace('MAPI')
        inbox = namespace.GetDefaultFolder(6)  # 6 = Inbox
        
        messages = inbox.Items
        messages.Sort('[ReceivedTime]', True)
        
        # Filter for unread and date range
        since_date = datetime.now() - timedelta(days=days_back)
        since_str = since_date.strftime('%m/%d/%Y')
        
        try:
            # Try to restrict to unread messages
            messages = messages.Restrict('[UnRead] = True')
        except Exception:
            pass
        
        count = 0
        for message in messages:
            if count >= max_emails:
                break
            try:
                received_time = message.ReceivedTime
                if received_time.replace(tzinfo=None) < since_date:
                    break
                    
                email_data = {
                    'source': 'outlook',
                    'sender': str(message.SenderEmailAddress) if hasattr(message, 'SenderEmailAddress') else str(message.Sender),
                    'subject': str(message.Subject),
                    'received': received_time.isoformat() if hasattr(received_time, 'isoformat') else str(received_time),
                    'body': str(message.Body)[:2000] if hasattr(message, 'Body') else '',
                    'preview': str(message.Body)[:500] if hasattr(message, 'Body') else ''
                }
                emails.append(email_data)
                count += 1
            except Exception:
                continue
                
    except ImportError:
        raise Exception("Outlook access requires pywin32. Install with: pip install pywin32")
    except Exception as e:
        raise Exception(f"Outlook error: {str(e)}")
    
    return emails


def _get_gmail_unread(max_emails: int, days_back: int) -> List[Dict]:
    """Retrieve unread emails from Gmail using IMAP."""
    emails = []
    
    # Try to get credentials from environment or config
    import os
    gmail_user = os.environ.get('GMAIL_USER')
    gmail_pass = os.environ.get('GMAIL_APP_PASSWORD')
    
    if not gmail_user or not gmail_pass:
        # Try to read from config file
        config_paths = [
            os.path.expanduser('~/.config/email_triage/config.json'),
            os.path.expanduser('~/.email_triage.json'),
            'email_config.json'
        ]
        for config_path in config_paths:
            if os.path.exists(config_path):
                try:
                    with open(config_path, 'r') as f:
                        config = json.load(f)
                        gmail_user = config.get('gmail_user')
                        gmail_pass = config.get('gmail_app_password')
                        break
                except Exception:
                    continue
    
    if not gmail_user or not gmail_pass:
        raise Exception("Gmail credentials not found. Set GMAIL_USER and GMAIL_APP_PASSWORD environment variables or create config file at ~/.config/email_triage/config.json")
    
    try:
        mail = imaplib.IMAP4_SSL('imap.gmail.com')
        mail.login(gmail_user, gmail_pass)
        mail.select('inbox')
        
        # Search for unread emails
        since_date = (datetime.now() - timedelta(days=days_back)).strftime('%d-%b-%Y')
        search_criteria = f'(UNSEEN SINCE "{since_date}")'
        
        status, messages = mail.search(None, search_criteria)
        
        if status != 'OK' or not messages[0]:
            mail.logout()
            return []
        
        message_ids = messages[0].split()[:max_emails]
        
        for msg_id in message_ids:
            status, msg_data = mail.fetch(msg_id, '(RFC822)')
            if status != 'OK':
                continue
            
            raw_email = msg_data[0][1]
            email_message = email.message_from_bytes(raw_email)
            
            # Extract body
            body = ''
            preview = ''
            if email_message.is_multipart():
                for part in email_message.walk():
                    content_type = part.get_content_type()
                    if content_type == 'text/plain':
                        try:
                            body = part.get_payload(decode=True).decode('utf-8', errors='ignore')
                            preview = body[:500]
                            break
                        except Exception:
                            continue
            else:
                try:
                    body = email_message.get_payload(decode=True).decode('utf-8', errors='ignore')
                    preview = body[:500]
                except Exception:
                    pass
            
            # Get sender
            sender = email_message.get('From', 'Unknown')
            # Clean up sender (extract email if in format "Name <email>")
            match = re.search(r'<(.+?)>', sender)
            if match:
                sender = match.group(1)
            
            # Get date
            date_str = email_message.get('Date', '')
            received = date_str
            
            email_data = {
                'source': 'gmail',
                'sender': sender,
                'subject': email_message.get('Subject', '(No subject)'),
                'received': received,
                'body': body[:2000],
                'preview': preview
            }
            emails.append(email_data)
        
        mail.logout()
        
    except Exception as e:
        raise Exception(f"Gmail IMAP error: {str(e)}")
    
    return emails


def _categorize_email(email_data: Dict) -> Dict:
    """Categorize email as urgent, actie, or informatief based on content analysis."""
    subject = email_data.get('subject', '').lower()
    body = email_data.get('body', '').lower()
    sender = email_data.get('sender', '').lower()
    combined = subject + ' ' + body
    
    # Priority score (0-100)
    priority_score = 50
    category = 'informatief'
    reason = []
    
    # URGENT keywords (Dutch and English)
    urgent_keywords = [
        'spoed', 'urgent', 'asap', 'zo snel mogelijk', 'onmiddellijk',
        'direct', 'dringend', 'critical', 'immediately', 'deadline',
        'vandaag', 'today', 'nu', 'now', 'actie vereist', 'action required',
        'overdue', 'achterstallig', 'vertraagd', 'delayed',
        'factuur', 'invoice', 'betaling', 'payment',
        'belangrijk', 'important', 'priority', 'prioriteit'
    ]
    
    # ACTIE keywords
    actie_keywords = [
        'actie', 'action', 'reactie nodig', 'response needed',
        'reageren', 'reply', 'bevestig', 'confirm',
        'keuring', 'inspection', 'afspraak', 'appointment',
        'meeting', 'overleg', 'consultation', 'review',
        'goedkeuring', 'approval', 'akkoord', 'goedkeuren',
        'aanvraag', 'application', 'aanmelding', 'registration',
        'update nodig', 'update required', 'invullen', 'fill in'
    ]
    
    # INFO keywords (negative indicators for urgency)
    info_keywords = [
        'nieuwsbrief', 'newsletter', 'update', 'nieuws',
        'marketing', 'promotie', 'aanbieding', 'offer',
        'notificatie', 'notification', 'status update',
        'samenvatting', 'summary', 'overzicht', 'overview',
        'bericht', 'message', 'informatie', 'information'
    ]
    
    # Check for urgent indicators
    urgent_matches = []
    for keyword in urgent_keywords:
        if keyword in combined:
            urgent_matches.append(keyword)
            priority_score += 15
    
    if urgent_matches:
        category = 'urgent'
        reason.append(f"Dringende termen gevonden: {', '.join(urgent_matches[:3])}")
    
    # Check for action indicators
    actie_matches = []
    for keyword in actie_keywords:
        if keyword in combined:
            actie_matches.append(keyword)
            priority_score += 10
    
    if actie_matches and category != 'urgent':
        category = 'actie'
        reason.append(f"Actie-termen gevonden: {', '.join(actie_matches[:3])}")
    
    # Check sender patterns
    important_senders = [
        'fermion', 'advies', 'belasting', 'tax', 'kvk', 'chamber of commerce',
        'gemeente', 'municipality', 'bank', 'verzekering', 'insurance',
        'vve', 'v.v.e.', 'makelaar', 'broker'
    ]
    
    for important in important_senders:
        if important in sender:
            priority_score += 10
            if category == 'informatief':
                category = 'actie'
            reason.append(f"Belangrijke afzender: {important}")
            break
    
    # Check for dates/deadlines
    date_patterns = [
        r'deadline[\s:]*([\d\-]+)',
        r'voor[\s]+(\d{1,2}[\-/\.])',
        r'uiterlijk[\s]+(\d{1,2}[\-/\.])',
        r'before[\s]+(\w+)',
        r'by[\s]+(\w+)'
    ]
    
    for pattern in date_patterns:
        if re.search(pattern, combined):
            priority_score += 15
            if category == 'informatief':
                category = 'actie'
            reason.append("Deadline/datum gevonden")
            break
    
    # Reduce priority for clear info/newsletter patterns
    info_count = 0
    for keyword in info_keywords:
        if keyword in combined:
            info_count += 1
    
    if info_count >= 2 and category == 'informatief':
        priority_score -= 20
        reason.append("Informatief/Newsletter karakter")
    
    # Cap priority score
    priority_score = max(0, min(100, priority_score))
    
    email_data['category'] = category
    email_data['priority_score'] = priority_score
    email_data['reason'] = '; '.join(reason) if reason else 'Geen specifieke indicatoren'
    
    return email_data


def _format_output(results: Dict, format_type: str) -> str:
    """Format results for display."""
    if format_type == 'json':
        return tool_ok(results, f"Triage complete: {results['summary']['total']} emails")
    
    if format_type == 'detailed':
        lines = [
            "=" * 60,
            f"EMAIL TRIAGE RAPPORT - {results['timestamp']}",
            "=" * 60,
            f"Bronnen gecheckt: {', '.join(results['sources_checked'])}",
            "",
            f"TOTAAL: {results['summary']['total']} | "
            f"URGENT: {results['summary']['urgent']} | "
            f"ACTIE: {results['summary']['actie']} | "
            f"INFORMATIEF: {results['summary']['informatief']}",
            "",
            "-" * 60
        ]
        
        for i, email in enumerate(results['emails'], 1):
            lines.extend([
                f"\n[{i}] {email['category'].upper()} (Score: {email['priority_score']})",
                f"Van: {email['sender']}",
                f"Onderwerp: {email['subject']}",
                f"Ontvangen: {email['received']}",
                f"Bron: {email['source']}",
                f"Reden: {email['reason']}",
                f"Preview: {email['preview'][:200]}..." if len(email['preview']) > 200 else f"Preview: {email['preview']}",
                "-" * 40
            ])
        
        if 'outlook_error' in results:
            lines.append(f"\n⚠ Outlook fout: {results['outlook_error']}")
        if 'gmail_error' in results:
            lines.append(f"\n⚠ Gmail fout: {results['gmail_error']}")
        
        return tool_ok(results, '\n'.join(lines))
    
    # Summary format (default)
    lines = [
        "📧 EMAIL TRIAGE - SAMENVATTING",
        f"Tijd: {results['timestamp'][:19]}",
        f"Bronnen: {', '.join(results['sources_checked'])}",
        "",
        f"🔴 URGENT: {results['summary']['urgent']} | "
        f"🟡 ACTIE: {results['summary']['actie']} | "
        f"🔵 INFORMATIEF: {results['summary']['informatief']}",
        f"Totaal: {results['summary']['total']} ongelezen",
        "",
        "TOP PRIORITEITEN:"
    ]
    
    # Show top 10 by priority
    top_emails = results['emails'][:10]
    for email in top_emails:
        icon = '🔴' if email['category'] == 'urgent' else ('🟡' if email['category'] == 'actie' else '🔵')
        subject = email['subject'][:50] + '...' if len(email['subject']) > 50 else email['subject']
        lines.append(f"{icon} [{email['source']}] {subject}")
        lines.append(f"   Van: {email['sender'][:40]} | Score: {email['priority_score']}")
    
    if len(results['emails']) > 10:
        lines.append(f"\n... en {len(results['emails']) - 10} andere emails")
    
    if 'outlook_error' in results:
        lines.append(f"\n⚠ Outlook kon niet worden geraadpleegd: {results['outlook_error']}")
    if 'gmail_error' in results:
        lines.append(f"\n⚠ Gmail kon niet worden geraadpleegd: {results['gmail_error']}")
    
    return tool_ok(results, '\n'.join(lines))
