#!/bin/bash
# Call Transcriber - runs via cron, processes recent Aircall recordings
# Downloads recordings, transcribes via Anthropic, posts summaries to Slack + GHL

set -euo pipefail

SECRETS_DIR="$HOME/.openclaw/secrets"
STATE_FILE="$HOME/.openclaw/workspace/scripts/.last-transcribed-call"
AIRCALL_KEY=$(cat "$SECRETS_DIR/aircall-api-key.txt")
ANTHROPIC_KEY=$(cat "$SECRETS_DIR/anthropic-api-key.txt")
SLACK_TOKEN=$(cat "$SECRETS_DIR/slack-token.txt")
GHL_V2_TOKEN=$(cat "$SECRETS_DIR/ghl-v2-token.txt")
GHL_API_KEY=$(cat "$SECRETS_DIR/ghl-api-key.txt")
SLACK_CHANNEL="CDP3Y6YB0"
GHL_LOCATION="BvrCS522k5EuY6TbZQsw"

# Get last processed call timestamp (default: 1 hour ago)
LAST_TS=$(cat "$STATE_FILE" 2>/dev/null || echo "0")

# Get recent calls from Aircall
CALLS=$(curl -s "https://api.aircall.io/v1/calls?order=desc&per_page=10" -u "$AIRCALL_KEY:")

# Process each call with a recording that we haven't processed yet
echo "$CALLS" | python3 -c "
import json, sys, subprocess, os, time, urllib.request, tempfile

data = json.load(sys.stdin)
last_ts = int('${LAST_TS}')
secrets_dir = '${SECRETS_DIR}'
anthropic_key = open(f'{secrets_dir}/anthropic-api-key.txt').read().strip()
slack_token = open(f'{secrets_dir}/slack-token.txt').read().strip()
ghl_v2_token = open(f'{secrets_dir}/ghl-v2-token.txt').read().strip()
ghl_api_key = open(f'{secrets_dir}/ghl-api-key.txt').read().strip()
slack_channel = '${SLACK_CHANNEL}'
ghl_location = '${GHL_LOCATION}'
state_file = '${STATE_FILE}'
import urllib.request as ur

max_ts = last_ts

for call in data.get('calls', []):
    call_ts = call.get('started_at', 0)
    duration = call.get('duration', 0)
    recording_url = call.get('recording', '')
    voicemail_url = call.get('voicemail', '')
    audio_url = recording_url or voicemail_url
    caller = call.get('raw_digits', 'unknown')
    direction = call.get('direction', 'unknown')
    user = call.get('user') or {}
    answered_by = user.get('name', 'nobody')
    
    # Skip if already processed or no recording or too short
    if call_ts <= last_ts:
        continue
    if not audio_url:
        continue
    if duration < 15:
        continue
    
    print(f'Processing call from {caller} ({duration}s, started {call_ts})')
    
    try:
        # Download audio to temp file
        tmp = tempfile.NamedTemporaryFile(suffix='.mp3', delete=False)
        req = ur.Request(audio_url)
        with ur.urlopen(req) as resp:
            audio_data = resp.read()
        tmp.write(audio_data)
        tmp.close()
        print(f'  Downloaded {len(audio_data)} bytes')
        
        # Transcribe with local Whisper
        result = subprocess.run(
            ['whisper', tmp.name, '--model', 'base', '--language', 'en', '--output_format', 'txt', '--output_dir', '/tmp/'],
            capture_output=True, text=True, timeout=300
        )
        
        # Read transcript
        txt_file = tmp.name.replace('.mp3', '.txt')
        txt_base = os.path.splitext(os.path.basename(tmp.name))[0]
        txt_path = f'/tmp/{txt_base}.txt'
        
        transcript = None
        if os.path.exists(txt_path):
            transcript = open(txt_path).read().strip()
        
        os.unlink(tmp.name)
        if os.path.exists(txt_path):
            os.unlink(txt_path)
        
        if not transcript:
            print('  No transcript returned')
            max_ts = max(max_ts, call_ts)
            continue
        
        print(f'  Transcribed: {transcript[:80]}...')
        
        # Summarize with Claude
        sum_body = json.dumps({
            'model': 'claude-opus-4-20250514',
            'max_tokens': 300,
            'messages': [{
                'role': 'user',
                'content': f'Summarize this phone call for a cleaning company CRM record. Be concise (2-4 sentences). Include: what the customer wanted, any decisions made, and any follow-up needed.\n\nCall: {direction}, {caller}, answered by {answered_by}, {duration//60}m {duration%60}s\n\nTranscript:\n{transcript}'
            }]
        }).encode()
        
        sum_req = ur.Request('https://api.anthropic.com/v1/messages', data=sum_body, headers={
            'x-api-key': anthropic_key,
            'anthropic-version': '2023-06-01',
            'content-type': 'application/json'
        })
        
        with ur.urlopen(sum_req, timeout=60) as resp:
            sum_result = json.loads(resp.read())
        
        summary = next((b['text'] for b in sum_result.get('content', []) if b['type'] == 'text'), None)
        print(f'  Summary: {summary[:80]}...' if summary else '  No summary')
        
        # Post summary to Slack
        if summary:
            slack_msg = f':clipboard: *Call Summary* ({caller}):\n{summary}'
            slack_body = json.dumps({'channel': slack_channel, 'text': slack_msg}).encode()
            slack_req = ur.Request('https://slack.com/api/chat.postMessage', data=slack_body, headers={
                'Authorization': f'Bearer {slack_token}',
                'Content-Type': 'application/json'
            })
            ur.urlopen(slack_req)
            print('  Posted to Slack')
        
        # Post transcript + summary to GHL
        search_url = f'https://services.leadconnectorhq.com/contacts/search/duplicate?locationId={ghl_location}&number={ur.quote(caller)}'
        search_req = ur.Request(search_url, headers={
            'Authorization': f'Bearer {ghl_v2_token}',
            'Version': '2021-07-28',
            'User-Agent': 'NMC-CallTranscriber/1.0'
        })
        with ur.urlopen(search_req) as resp:
            search_data = json.loads(resp.read())
        
        contact_id = (search_data.get('contact') or {}).get('id')
        
        if contact_id and summary:
            msg = f'📋 Call Summary ({duration//60}m {duration%60}s)\n{summary}'
            msg_body = json.dumps({'type': 'SMS', 'contactId': contact_id, 'message': msg}).encode()
            msg_req = ur.Request('https://services.leadconnectorhq.com/conversations/messages/inbound', data=msg_body, headers={
                'Authorization': f'Bearer {ghl_v2_token}',
                'Version': '2021-07-28',
                'Content-Type': 'application/json',
                'User-Agent': 'NMC-CallTranscriber/1.0'
            })
            ur.urlopen(msg_req)
            print(f'  Posted summary to GHL conversation for {contact_id}')
        else:
            print(f'  No GHL contact for {caller}')
        
    except Exception as e:
        print(f'  Error: {e}')
    
    max_ts = max(max_ts, call_ts)

# Update state
if max_ts > last_ts:
    with open(state_file, 'w') as f:
        f.write(str(max_ts))
    print(f'Updated last processed to {max_ts}')
else:
    print('No new calls to process')
"
