"""
AppleScript wrappers for Apple native apps.
All operations use osascript to execute AppleScript commands locally.
No network calls, no third-party dependencies.
"""

import subprocess
import json
import sqlite3
import os
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta


def run_applescript(script: str) -> str:
    """Execute an AppleScript and return the output."""
    result = subprocess.run(
        ['osascript', '-e', script],
        capture_output=True,
        text=True
    )
    if result.returncode != 0:
        raise Exception(f"AppleScript error: {result.stderr}")
    return result.stdout.strip()


def run_applescript_list(script: str) -> List[str]:
    """Execute an AppleScript that returns a list."""
    result = run_applescript(script)
    if not result:
        return []
    # AppleScript returns comma-separated values
    return [item.strip() for item in result.split(', ') if item.strip()]


# =============================================================================
# JSON HELPER FOR APPLESCRIPT
# =============================================================================

# AppleScript helper to escape strings for JSON output
# Note: In this Python string, we use ASCII character codes to avoid escaping issues
# ASCII 34 = double quote, ASCII 92 = backslash
APPLESCRIPT_JSON_HELPERS = '''
on escapeForJSON(theText)
    if theText is missing value then return "null"
    set theText to theText as text
    set resultText to ""
    set backslashChar to ASCII character 92
    set quoteChar to ASCII character 34
    repeat with i from 1 to length of theText
        set theChar to character i of theText
        if theChar is backslashChar then
            set resultText to resultText & backslashChar & backslashChar
        else if theChar is quoteChar then
            set resultText to resultText & backslashChar & quoteChar
        else if theChar is (ASCII character 10) then
            set resultText to resultText & backslashChar & "n"
        else if theChar is (ASCII character 13) then
            set resultText to resultText & backslashChar & "r"
        else if theChar is (ASCII character 9) then
            set resultText to resultText & backslashChar & "t"
        else
            set resultText to resultText & theChar
        end if
    end repeat
    return resultText
end escapeForJSON

on jsonString(theValue)
    if theValue is missing value then return "null"
    set quoteChar to ASCII character 34
    return quoteChar & my escapeForJSON(theValue) & quoteChar
end jsonString

on jsonNumber(theValue)
    if theValue is missing value then return "null"
    return theValue as text
end jsonNumber

on jsonBool(theValue)
    if theValue then return "true"
    return "false"
end jsonBool
'''


def run_applescript_json(script: str) -> Any:
    """Execute AppleScript that returns JSON and parse it."""
    # Prepend JSON helpers to the script
    full_script = APPLESCRIPT_JSON_HELPERS + "\n" + script
    result = run_applescript(full_script)
    if not result:
        return []
    try:
        return json.loads(result)
    except json.JSONDecodeError as e:
        # Fallback: return raw result with error info
        return [{"error": f"JSON parse error: {e}", "raw": result}]


# =============================================================================
# MESSAGES / iMESSAGE (using SQLite for reliability)
# =============================================================================

MESSAGES_DB = os.path.expanduser("~/Library/Messages/chat.db")

def _get_messages_db():
    """Get connection to Messages database."""
    if not os.path.exists(MESSAGES_DB):
        raise Exception("Messages database not found. Grant Full Disk Access to Terminal.")
    return sqlite3.connect(MESSAGES_DB)

def list_message_chats() -> List[Dict[str, Any]]:
    """Get all iMessage/SMS conversations."""
    script = '''
    tell application "Messages"
        set chatList to {}
        repeat with c in chats
            set chatInfo to {id:(id of c), participants:""}
            try
                set participantNames to {}
                repeat with p in participants of c
                    set end of participantNames to (name of p)
                end repeat
                set chatInfo's participants to participantNames
            end try
            set end of chatList to chatInfo
        end repeat
        return chatList
    end tell
    '''
    try:
        result = run_applescript(script)
        # Parse the AppleScript output
        chats = []
        if result:
            # Simple parsing - AppleScript returns structured data
            lines = result.replace('{{', '').replace('}}', '').split('}, {')
            for line in lines:
                if 'id:' in line:
                    chat = {}
                    parts = line.split(', ')
                    for part in parts:
                        if ':' in part:
                            key, value = part.split(':', 1)
                            chat[key.strip()] = value.strip()
                    if chat:
                        chats.append(chat)
        return chats
    except Exception as e:
        return [{"error": str(e)}]


def get_chat_messages(chat_id: str, limit: int = 20) -> List[Dict[str, Any]]:
    """Get messages from a specific chat using SQLite."""
    try:
        conn = _get_messages_db()
        cursor = conn.cursor()

        # Extract phone/email from chat_id (format: any;-;+1234567890)
        identifier = chat_id.split(';')[-1] if ';' in chat_id else chat_id

        query = """
        SELECT
            m.text,
            m.is_from_me,
            datetime(m.date/1000000000 + 978307200, 'unixepoch', 'localtime') as timestamp,
            h.id as sender
        FROM message m
        LEFT JOIN handle h ON m.handle_id = h.ROWID
        LEFT JOIN chat_message_join cmj ON m.ROWID = cmj.message_id
        LEFT JOIN chat c ON cmj.chat_id = c.ROWID
        WHERE c.chat_identifier LIKE ?
        ORDER BY m.date DESC
        LIMIT ?
        """

        cursor.execute(query, (f'%{identifier}%', limit))
        rows = cursor.fetchall()
        conn.close()

        messages = []
        for row in rows:
            text, is_from_me, timestamp, sender = row
            messages.append({
                "content": text or "",
                "sender": "Me" if is_from_me else (sender or "Unknown"),
                "timestamp": timestamp or ""
            })

        return messages if messages else [{"info": "No messages found"}]
    except Exception as e:
        return [{"error": str(e)}]


def get_recent_messages(limit: int = 20) -> List[Dict[str, Any]]:
    """Get recent messages across all chats using SQLite."""
    try:
        conn = _get_messages_db()
        cursor = conn.cursor()

        query = """
        SELECT
            m.text,
            m.is_from_me,
            datetime(m.date/1000000000 + 978307200, 'unixepoch', 'localtime') as timestamp,
            h.id as sender,
            c.chat_identifier
        FROM message m
        LEFT JOIN handle h ON m.handle_id = h.ROWID
        LEFT JOIN chat_message_join cmj ON m.ROWID = cmj.message_id
        LEFT JOIN chat c ON cmj.chat_id = c.ROWID
        WHERE m.text IS NOT NULL AND m.text != ''
        ORDER BY m.date DESC
        LIMIT ?
        """

        cursor.execute(query, (limit,))
        rows = cursor.fetchall()
        conn.close()

        messages = []
        for row in rows:
            text, is_from_me, timestamp, sender, chat_id = row
            messages.append({
                "content": text or "",
                "sender": "Me" if is_from_me else (sender or "Unknown"),
                "timestamp": timestamp or "",
                "chat": chat_id or ""
            })

        return messages if messages else [{"info": "No messages found"}]
    except Exception as e:
        return [{"error": str(e)}]


def search_messages(query: str) -> List[Dict[str, Any]]:
    """Search messages by content using SQLite."""
    try:
        conn = _get_messages_db()
        cursor = conn.cursor()

        sql = """
        SELECT
            m.text,
            m.is_from_me,
            datetime(m.date/1000000000 + 978307200, 'unixepoch', 'localtime') as timestamp,
            h.id as sender,
            c.chat_identifier
        FROM message m
        LEFT JOIN handle h ON m.handle_id = h.ROWID
        LEFT JOIN chat_message_join cmj ON m.ROWID = cmj.message_id
        LEFT JOIN chat c ON cmj.chat_id = c.ROWID
        WHERE m.text LIKE ?
        ORDER BY m.date DESC
        LIMIT 50
        """

        cursor.execute(sql, (f'%{query}%',))
        rows = cursor.fetchall()
        conn.close()

        messages = []
        for row in rows:
            text, is_from_me, timestamp, sender, chat_id = row
            messages.append({
                "content": text or "",
                "sender": "Me" if is_from_me else (sender or "Unknown"),
                "timestamp": timestamp or "",
                "chat": chat_id or ""
            })

        return messages if messages else [{"info": f"No messages matching '{query}'"}]
    except Exception as e:
        return [{"error": str(e)}]


def send_imessage(recipient: str, message: str) -> Dict[str, Any]:
    """Send an iMessage or SMS to a recipient (phone number or email)."""
    # Escape quotes in message
    safe_message = message.replace('"', '\\"').replace("'", "\\'")
    script = f'''
    tell application "Messages"
        set targetService to 1st account whose service type = iMessage
        set targetBuddy to participant "{recipient}" of targetService
        send "{safe_message}" to targetBuddy
        return "Message sent successfully"
    end tell
    '''
    try:
        result = run_applescript(script)
        return {"success": True, "message": result}
    except Exception as e:
        return {"success": False, "error": str(e)}


# =============================================================================
# NOTES
# =============================================================================

def list_note_folders() -> List[Dict[str, Any]]:
    """List all note folders."""
    script = '''
    tell application "Notes"
        set folderList to {}
        repeat with f in folders
            set noteCount to count of notes in f
            set folderInfo to {name:(name of f), noteCount:noteCount}
            set end of folderList to folderInfo
        end repeat
        return folderList
    end tell
    '''
    try:
        result = run_applescript(script)
        folders = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                folder = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        folder[key.strip()] = value.strip()
                if folder:
                    folders.append(folder)
        return folders
    except Exception as e:
        return [{"error": str(e)}]


def list_notes(folder: Optional[str] = None) -> List[Dict[str, Any]]:
    """List all notes, optionally filtered by folder."""
    if folder:
        script = f'''
        tell application "Notes"
            set noteList to {{}}
            repeat with n in notes of folder "{folder}"
                set noteInfo to {{name:(name of n), created:(creation date of n as string), modified:(modification date of n as string)}}
                set end of noteList to noteInfo
            end repeat
            return noteList
        end tell
        '''
    else:
        script = '''
        tell application "Notes"
            set noteList to {}
            repeat with n in notes
                set noteInfo to {name:(name of n), created:(creation date of n as string), modified:(modification date of n as string)}
                set end of noteList to noteInfo
            end repeat
            return noteList
        end tell
        '''
    try:
        result = run_applescript(script)
        notes = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                note = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        note[key.strip()] = value.strip()
                if note:
                    notes.append(note)
        return notes
    except Exception as e:
        return [{"error": str(e)}]


def get_note(note_name: str) -> Dict[str, Any]:
    """Get the content of a specific note by name."""
    safe_name = note_name.replace('"', '\\"')
    script = f'''
    tell application "Notes"
        set targetNote to first note whose name is "{safe_name}"
        return {{name:(name of targetNote), body:(plaintext of targetNote), created:(creation date of targetNote as string), modified:(modification date of targetNote as string)}}
    end tell
    '''
    try:
        result = run_applescript(script)
        note = {"raw": result}
        if result:
            # Parse the result
            result = result.strip('{}')
            parts = result.split(', ')
            for part in parts:
                if ':' in part:
                    key, value = part.split(':', 1)
                    note[key.strip()] = value.strip()
        return note
    except Exception as e:
        return {"error": str(e)}


def create_note(title: str, body: str, folder: Optional[str] = None) -> Dict[str, Any]:
    """Create a new note."""
    safe_title = title.replace('"', '\\"')
    safe_body = body.replace('"', '\\"')

    if folder:
        script = f'''
        tell application "Notes"
            tell folder "{folder}"
                make new note with properties {{name:"{safe_title}", body:"{safe_body}"}}
            end tell
            return "Note created successfully"
        end tell
        '''
    else:
        script = f'''
        tell application "Notes"
            make new note with properties {{name:"{safe_title}", body:"{safe_body}"}}
            return "Note created successfully"
        end tell
        '''
    try:
        result = run_applescript(script)
        return {"success": True, "message": result}
    except Exception as e:
        return {"success": False, "error": str(e)}


def search_notes(query: str) -> List[Dict[str, Any]]:
    """Search notes by content or title."""
    script = f'''
    tell application "Notes"
        set foundNotes to {{}}
        repeat with n in notes
            if (name of n) contains "{query}" or (plaintext of n) contains "{query}" then
                set noteInfo to {{name:(name of n), created:(creation date of n as string)}}
                set end of foundNotes to noteInfo
            end if
        end repeat
        return foundNotes
    end tell
    '''
    try:
        result = run_applescript(script)
        notes = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                note = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        note[key.strip()] = value.strip()
                if note:
                    notes.append(note)
        return notes
    except Exception as e:
        return [{"error": str(e)}]


# =============================================================================
# REMINDERS
# =============================================================================

def list_reminder_lists() -> List[Dict[str, Any]]:
    """List all reminder lists."""
    # Fast bulk query - just get names without counting (counting is slow)
    script = 'tell application "Reminders" to get name of every list'
    try:
        result = run_applescript(script)
        lists = []
        if result:
            names = [n.strip() for n in result.split(', ') if n.strip()]
            for name in names:
                lists.append({"name": name})
        return lists
    except Exception as e:
        return [{"error": str(e)}]


def list_reminders(list_name: Optional[str] = None, show_completed: bool = False) -> List[Dict[str, Any]]:
    """List reminders, optionally filtered by list and completion status."""
    # Use fast bulk query instead of slow loop
    if list_name:
        if show_completed:
            script = f'tell application "Reminders" to get name of reminders of list "{list_name}"'
        else:
            script = f'tell application "Reminders" to get name of reminders of list "{list_name}" whose completed is false'
    else:
        if show_completed:
            script = 'tell application "Reminders" to get name of every reminder'
        else:
            script = 'tell application "Reminders" to get name of (reminders whose completed is false)'
    try:
        result = run_applescript(script)
        reminders = []
        if result:
            names = [n.strip() for n in result.split(', ') if n.strip()]
            for name in names:
                reminders.append({"name": name, "completed": show_completed})
        return reminders
    except Exception as e:
        return [{"error": str(e)}]


def parse_date_for_applescript(date_str: str) -> str:
    """Parse a date string and return AppleScript-compatible format.

    Accepts various formats:
    - ISO: 2026-01-30, 2026-01-30T17:00:00
    - US: January 30, 2026, January 30, 2026 5:00 PM
    - UK/Indian: 30 January 2026, 30/1/2026
    - Numeric: 30-01-2026, 01/30/2026

    Returns: "30 January 2026 5:00:00 PM" format for AppleScript
    """
    from dateutil import parser as date_parser
    try:
        # Parse the date string flexibly
        dt = date_parser.parse(date_str, dayfirst=True)
        # Format for AppleScript (UK/Indian locale): "30 January 2026 5:00:00 PM"
        return dt.strftime("%-d %B %Y %-I:%M:%S %p")
    except Exception:
        # Fallback: return as-is and let AppleScript handle it
        return date_str


def create_reminder(title: str, list_name: Optional[str] = None, due_date: Optional[str] = None, notes: Optional[str] = None) -> Dict[str, Any]:
    """Create a new reminder."""
    safe_title = title.replace('"', '\\"')

    properties = f'name:"{safe_title}"'
    if notes:
        safe_notes = notes.replace('"', '\\"')
        properties += f', body:"{safe_notes}"'
    if due_date:
        formatted_date = parse_date_for_applescript(due_date)
        properties += f', due date:(date "{formatted_date}")'

    if list_name:
        script = f'''
        tell application "Reminders"
            tell list "{list_name}"
                make new reminder with properties {{{properties}}}
            end tell
            return "Reminder created successfully"
        end tell
        '''
    else:
        script = f'''
        tell application "Reminders"
            make new reminder with properties {{{properties}}}
            return "Reminder created successfully"
        end tell
        '''
    try:
        result = run_applescript(script)
        return {"success": True, "message": result}
    except Exception as e:
        return {"success": False, "error": str(e)}


def complete_reminder(reminder_name: str) -> Dict[str, Any]:
    """Mark a reminder as complete."""
    safe_name = reminder_name.replace('"', '\\"')
    script = f'''
    tell application "Reminders"
        set targetReminder to first reminder whose name is "{safe_name}"
        set completed of targetReminder to true
        return "Reminder completed"
    end tell
    '''
    try:
        result = run_applescript(script)
        return {"success": True, "message": result}
    except Exception as e:
        return {"success": False, "error": str(e)}


def search_reminders(query: str) -> List[Dict[str, Any]]:
    """Search reminders by name."""
    script = f'''
    tell application "Reminders"
        set foundReminders to {{}}
        repeat with r in reminders
            if (name of r) contains "{query}" then
                set info to {{name:(name of r), completed:(completed of r)}}
                set end of foundReminders to info
            end if
        end repeat
        return foundReminders
    end tell
    '''
    try:
        result = run_applescript(script)
        reminders = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                reminder = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        reminder[key.strip()] = value.strip()
                if reminder:
                    reminders.append(reminder)
        return reminders
    except Exception as e:
        return [{"error": str(e)}]


# =============================================================================
# CALENDAR
# =============================================================================

def list_calendars() -> List[Dict[str, Any]]:
    """List all calendars."""
    script = '''
    tell application "Calendar"
        set calList to {}
        repeat with c in calendars
            set info to {name:(name of c), description:(description of c)}
            set end of calList to info
        end repeat
        return calList
    end tell
    '''
    try:
        result = run_applescript(script)
        calendars = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                cal = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        cal[key.strip()] = value.strip()
                if cal:
                    calendars.append(cal)
        return calendars
    except Exception as e:
        return [{"error": str(e)}]


def get_todays_events() -> List[Dict[str, Any]]:
    """Get today's calendar events."""
    script = '''
    tell application "Calendar"
        set today to current date
        set todayStart to today - (time of today)
        set todayEnd to todayStart + (1 * days)
        set eventList to {}
        repeat with c in calendars
            repeat with e in (events of c whose start date >= todayStart and start date < todayEnd)
                set info to {summary:(summary of e), startDate:(start date of e as string), endDate:(end date of e as string), location:(location of e)}
                set end of eventList to info
            end repeat
        end repeat
        return eventList
    end tell
    '''
    try:
        result = run_applescript(script)
        events = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                event = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        event[key.strip()] = value.strip()
                if event:
                    events.append(event)
        return events
    except Exception as e:
        return [{"error": str(e)}]


def get_events(calendar_name: Optional[str] = None, days_ahead: int = 7) -> List[Dict[str, Any]]:
    """Get events from a specific calendar or all calendars for the next N days."""
    if calendar_name:
        script = f'''
        tell application "Calendar"
            set today to current date
            set todayStart to today - (time of today)
            set futureDate to todayStart + ({days_ahead} * days)
            set eventList to {{}}
            set targetCal to calendar "{calendar_name}"
            repeat with e in (events of targetCal whose start date >= todayStart and start date < futureDate)
                set info to {{summary:(summary of e), startDate:(start date of e as string), endDate:(end date of e as string), location:(location of e)}}
                set end of eventList to info
            end repeat
            return eventList
        end tell
        '''
    else:
        script = f'''
        tell application "Calendar"
            set today to current date
            set todayStart to today - (time of today)
            set futureDate to todayStart + ({days_ahead} * days)
            set eventList to {{}}
            repeat with c in calendars
                repeat with e in (events of c whose start date >= todayStart and start date < futureDate)
                    set info to {{summary:(summary of e), startDate:(start date of e as string), endDate:(end date of e as string), location:(location of e)}}
                    set end of eventList to info
                end repeat
            end repeat
            return eventList
        end tell
        '''
    try:
        result = run_applescript(script)
        events = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                event = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        event[key.strip()] = value.strip()
                if event:
                    events.append(event)
        return events
    except Exception as e:
        return [{"error": str(e)}]


def create_event(title: str, calendar_name: str, start_date: str, end_date: str, location: Optional[str] = None, notes: Optional[str] = None) -> Dict[str, Any]:
    """Create a new calendar event. Dates should be in format: 'January 7, 2026 10:00 AM'"""
    safe_title = title.replace('"', '\\"')

    properties = f'summary:"{safe_title}", start date:(date "{start_date}"), end date:(date "{end_date}")'
    if location:
        safe_location = location.replace('"', '\\"')
        properties += f', location:"{safe_location}"'
    if notes:
        safe_notes = notes.replace('"', '\\"')
        properties += f', description:"{safe_notes}"'

    script = f'''
    tell application "Calendar"
        tell calendar "{calendar_name}"
            make new event with properties {{{properties}}}
        end tell
        return "Event created successfully"
    end tell
    '''
    try:
        result = run_applescript(script)
        return {"success": True, "message": result}
    except Exception as e:
        return {"success": False, "error": str(e)}


# =============================================================================
# CONTACTS
# =============================================================================

def list_contacts(limit: int = 50) -> List[Dict[str, Any]]:
    """List contacts."""
    script = f'''
    tell application "Contacts"
        set contactList to {{}}
        set contactCount to 0
        repeat with p in people
            if contactCount >= {limit} then exit repeat
            set info to {{name:(name of p)}}
            try
                set info's email to (value of first email of p)
            end try
            try
                set info's phone to (value of first phone of p)
            end try
            set end of contactList to info
            set contactCount to contactCount + 1
        end repeat
        return contactList
    end tell
    '''
    try:
        result = run_applescript(script)
        contacts = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                contact = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        contact[key.strip()] = value.strip()
                if contact:
                    contacts.append(contact)
        return contacts
    except Exception as e:
        return [{"error": str(e)}]


def search_contacts(query: str) -> List[Dict[str, Any]]:
    """Search contacts by name, email, or phone."""
    script = f'''
    tell application "Contacts"
        set foundContacts to {{}}
        repeat with p in people
            set matched to false
            if (name of p) contains "{query}" then set matched to true
            try
                repeat with e in emails of p
                    if (value of e) contains "{query}" then set matched to true
                end repeat
            end try
            try
                repeat with ph in phones of p
                    if (value of ph) contains "{query}" then set matched to true
                end repeat
            end try
            if matched then
                set info to {{name:(name of p)}}
                try
                    set info's email to (value of first email of p)
                end try
                try
                    set info's phone to (value of first phone of p)
                end try
                set end of foundContacts to info
            end if
        end repeat
        return foundContacts
    end tell
    '''
    try:
        result = run_applescript(script)
        contacts = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                contact = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        contact[key.strip()] = value.strip()
                if contact:
                    contacts.append(contact)
        return contacts
    except Exception as e:
        return [{"error": str(e)}]


def get_contact(name: str) -> Dict[str, Any]:
    """Get detailed information about a contact."""
    safe_name = name.replace('"', '\\"')
    script = f'''
    tell application "Contacts"
        set targetPerson to first person whose name is "{safe_name}"
        set info to {{name:(name of targetPerson)}}
        try
            set emailList to {{}}
            repeat with e in emails of targetPerson
                set end of emailList to (value of e)
            end repeat
            set info's emails to emailList
        end try
        try
            set phoneList to {{}}
            repeat with ph in phones of targetPerson
                set end of phoneList to (value of ph)
            end repeat
            set info's phones to phoneList
        end try
        try
            set info's company to (organization of targetPerson)
        end try
        try
            set info's jobTitle to (job title of targetPerson)
        end try
        try
            set info's note to (note of targetPerson)
        end try
        return info
    end tell
    '''
    try:
        result = run_applescript(script)
        contact = {"raw": result}
        if result:
            result = result.strip('{}')
            parts = result.split(', ')
            for part in parts:
                if ':' in part:
                    key, value = part.split(':', 1)
                    contact[key.strip()] = value.strip()
        return contact
    except Exception as e:
        return {"error": str(e)}


def get_contact_groups() -> List[Dict[str, Any]]:
    """List all contact groups."""
    script = '''
    tell application "Contacts"
        set groupList to {}
        repeat with g in groups
            set memberCount to count of people in g
            set info to {name:(name of g), memberCount:memberCount}
            set end of groupList to info
        end repeat
        return groupList
    end tell
    '''
    try:
        result = run_applescript(script)
        groups = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                group = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        group[key.strip()] = value.strip()
                if group:
                    groups.append(group)
        return groups
    except Exception as e:
        return [{"error": str(e)}]


# =============================================================================
# PHOTOS
# =============================================================================

def list_albums() -> List[Dict[str, Any]]:
    """List all photo albums."""
    script = '''
    tell application "Photos"
        set albumList to {}
        repeat with a in albums
            set photoCount to count of media items in a
            set info to {name:(name of a), photoCount:photoCount}
            set end of albumList to info
        end repeat
        return albumList
    end tell
    '''
    try:
        result = run_applescript(script)
        albums = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                album = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        album[key.strip()] = value.strip()
                if album:
                    albums.append(album)
        return albums
    except Exception as e:
        return [{"error": str(e)}]


def get_recent_photos(limit: int = 20) -> List[Dict[str, Any]]:
    """Get recent photos from the library."""
    script = f'''
    tell application "Photos"
        set photoList to {{}}
        set photoCount to 0
        repeat with m in media items
            if photoCount >= {limit} then exit repeat
            set info to {{id:(id of m), filename:(filename of m), date:(date of m as string)}}
            try
                set info's description to (description of m)
            end try
            set end of photoList to info
            set photoCount to photoCount + 1
        end repeat
        return photoList
    end tell
    '''
    try:
        result = run_applescript(script)
        photos = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                photo = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        photo[key.strip()] = value.strip()
                if photo:
                    photos.append(photo)
        return photos
    except Exception as e:
        return [{"error": str(e)}]


def get_album_photos(album_name: str, limit: int = 20) -> List[Dict[str, Any]]:
    """Get photos from a specific album."""
    script = f'''
    tell application "Photos"
        set targetAlbum to album "{album_name}"
        set photoList to {{}}
        set photoCount to 0
        repeat with m in media items of targetAlbum
            if photoCount >= {limit} then exit repeat
            set info to {{id:(id of m), filename:(filename of m), date:(date of m as string)}}
            try
                set info's description to (description of m)
            end try
            set end of photoList to info
            set photoCount to photoCount + 1
        end repeat
        return photoList
    end tell
    '''
    try:
        result = run_applescript(script)
        photos = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                photo = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        photo[key.strip()] = value.strip()
                if photo:
                    photos.append(photo)
        return photos
    except Exception as e:
        return [{"error": str(e)}]


def search_photos(query: str, limit: int = 20) -> List[Dict[str, Any]]:
    """Search photos by description/keywords."""
    script = f'''
    tell application "Photos"
        set foundPhotos to {{}}
        set photoCount to 0
        repeat with m in media items
            if photoCount >= {limit} then exit repeat
            try
                if (description of m) contains "{query}" or (filename of m) contains "{query}" then
                    set info to {{id:(id of m), filename:(filename of m), date:(date of m as string), description:(description of m)}}
                    set end of foundPhotos to info
                    set photoCount to photoCount + 1
                end if
            end try
        end repeat
        return foundPhotos
    end tell
    '''
    try:
        result = run_applescript(script)
        photos = []
        if result:
            entries = result.replace('{{', '').replace('}}', '').split('}, {')
            for entry in entries:
                photo = {}
                parts = entry.split(', ')
                for part in parts:
                    if ':' in part:
                        key, value = part.split(':', 1)
                        photo[key.strip()] = value.strip()
                if photo:
                    photos.append(photo)
        return photos
    except Exception as e:
        return [{"error": str(e)}]
