#!/usr/bin/env python3
"""
Manager CLI - Follow-up management tool using Supabase RPCs

Usage:
  python manager_cli.py list_due --days 21
  python manager_cli.py done --id 123 --note "Called and closed"
  python manager_cli.py resched --id 123 --at "2025-12-15 09:00"
  python manager_cli.py nudge --id 123 --channel whatsapp --tag "Offer-Refresh-Dec"
"""
import os
import sys
import argparse
from datetime import datetime
from zoneinfo import ZoneInfo
from supabase import create_client


def get_supabase():
    """Create Supabase client."""
    url = os.getenv('SUPABASE_URL')
    key = os.getenv('SUPABASE_SERVICE_KEY')
    
    if not url or not key:
        print("❌ Error: SUPABASE_URL and SUPABASE_SERVICE_KEY must be set")
        sys.exit(1)
    
    return create_client(url, key)


def list_due(days: int):
    """List follow-ups due in next N days."""
    client = get_supabase()
    
    try:
        # Query the view
        result = client.table('v_followups_next_21d').select('*').execute()
        
        if not result.data:
            print(f"📭 No follow-ups due in the next {days} days")
            return
        
        # Filter by days if needed (view shows 21 days by default)
        followups = result.data
        
        # Print header
        print(f"\n📅 FOLLOW-UPS DUE IN NEXT {days} DAYS")
        print("=" * 100)
        print(f"{'ID':<6} {'Due At':<17} {'Name':<20} {'Reg':<12} {'Reason':<40}")
        print("-" * 100)
        
        # Print rows
        for fu in followups:
            fu_id = str(fu.get('id', 'N/A'))
            due_at = fu.get('due_at', 'N/A')[:16] if fu.get('due_at') else 'N/A'
            name = (fu.get('first_name', '') + ' ' + fu.get('last_name', '')).strip()[:20] or 'N/A'
            reg = fu.get('registration', 'N/A')[:12]
            reason = fu.get('reason', 'N/A')[:40]
            
            print(f"{fu_id:<6} {due_at:<17} {name:<20} {reg:<12} {reason:<40}")
        
        print("-" * 100)
        print(f"Total: {len(followups)} follow-up(s)\n")
    
    except Exception as e:
        print(f"❌ Error listing follow-ups: {e}")
        sys.exit(1)


def mark_done(followup_id: int, note: str = None):
    """Mark a follow-up as done."""
    client = get_supabase()
    
    try:
        # Call RPC
        params = {'p_followup_id': followup_id}
        if note:
            params['p_note'] = note
        
        result = client.rpc('mark_followup_done', params).execute()
        
        print(f"\n✅ Follow-up {followup_id} marked as DONE")
        if note:
            print(f"   Note: {note}")
        
        if result.data:
            print(f"   Completed at: {result.data.get('done_at', 'N/A')[:19]}")
        print()
    
    except Exception as e:
        print(f"❌ Error marking follow-up done: {e}")
        sys.exit(1)


def reschedule(followup_id: int, new_time_str: str):
    """Reschedule a follow-up to a new time."""
    client = get_supabase()
    
    try:
        # Parse the UK local time string
        tz = ZoneInfo("Europe/London")
        
        # Try to parse the datetime
        try:
            local_dt = datetime.strptime(new_time_str, "%Y-%m-%d %H:%M")
            local_dt = local_dt.replace(tzinfo=tz)
        except ValueError:
            print(f"❌ Error: Invalid datetime format. Use 'YYYY-MM-DD HH:MM'")
            print(f"   Example: 2025-12-15 09:00")
            sys.exit(1)
        
        # Convert to UTC for database
        utc_dt = local_dt.astimezone(ZoneInfo("UTC"))
        
        # Call RPC
        params = {
            'p_followup_id': followup_id,
            'p_new_due_at': utc_dt.isoformat()
        }
        
        result = client.rpc('reschedule_followup', params).execute()
        
        print(f"\n✅ Follow-up {followup_id} RESCHEDULED")
        print(f"   New time (UK): {local_dt.strftime('%Y-%m-%d %H:%M %Z')}")
        print(f"   New time (UTC): {utc_dt.strftime('%Y-%m-%d %H:%M:%S %Z')}")
        
        if result.data:
            print(f"   Database due_at: {result.data.get('due_at', 'N/A')[:19]}")
        print()
    
    except Exception as e:
        print(f"❌ Error rescheduling follow-up: {e}")
        sys.exit(1)


def queue_nudge(followup_id: int, channel: str = 'whatsapp', tag: str = None):
    """Queue a nudge from a follow-up."""
    client = get_supabase()
    
    try:
        # Call RPC
        params = {
            'p_followup_id': followup_id,
            'p_channel': channel
        }
        if tag:
            params['p_tag'] = tag
        
        result = client.rpc('queue_nudge_from_followup', params).execute()
        
        print(f"\n✅ Nudge QUEUED from follow-up {followup_id}")
        print(f"   Channel: {channel}")
        if tag:
            print(f"   Tag: {tag}")
        
        if result.data:
            pool_id = result.data.get('campaign_pool_id', 'N/A')
            print(f"   Campaign Pool ID: {pool_id}")
        print()
    
    except Exception as e:
        print(f"❌ Error queuing nudge: {e}")
        sys.exit(1)


def open_thread(agreement: str, thread_type: str = 'renewal'):
    """Open a thread for an agreement."""
    from tools import open_thread as open_thread_tool
    
    try:
        result = open_thread_tool(agreement, thread_type)
        
        print(f"\n✅ Thread OPENED")
        print(f"   Agreement: {agreement}")
        print(f"   Type: {thread_type}")
        print(f"   Status: {result.get('status', 'N/A')}")
        print(f"   Thread ID: {result.get('id', 'N/A')}")
        print()
    
    except Exception as e:
        print(f"❌ Error opening thread: {e}")
        sys.exit(1)


def seed_inbound(agreement: str, channel: str, text: str):
    """Seed an inbound message."""
    from tools import log_message
    
    try:
        log_message(
            agreement_ref=agreement,
            channel=channel,
            direction='inbound',
            message_text=text,
            intent_label=None,
            template_slug=None,
            source='customer',
            model=None
        )
        
        print(f"\n✅ Inbound message SEEDED")
        print(f"   Agreement: {agreement}")
        print(f"   Channel: {channel}")
        print(f"   Text: '{text}'")
        print(f"\n💡 Tip: Let Android_Handler_Live poll (~60s) to process this message\n")
    
    except Exception as e:
        print(f"❌ Error seeding inbound: {e}")
        sys.exit(1)


def recent_msgs(agreement: str, limit: int = 10):
    """Show recent messages for an agreement."""
    from tools import get_client, resolve_agreement_id
    
    try:
        client = get_client()
        agreement_id = resolve_agreement_id(agreement)
        
        if not agreement_id:
            print(f"❌ Agreement {agreement} not found")
            sys.exit(1)
        
        # Get recent messages
        result = client.table('contact_history') \
            .select('*') \
            .eq('agreement_id', agreement_id) \
            .order('happened_at', desc=True) \
            .limit(limit) \
            .execute()
        
        if not result.data:
            print(f"📭 No messages found for {agreement}")
            return
        
        print(f"\n📝 RECENT MESSAGES ({agreement})")
        print("=" * 100)
        
        for i, msg in enumerate(result.data, 1):
            direction_icon = "📥" if msg['direction'] == 'inbound' else "📤"
            direction = msg['direction']
            happened_at = msg.get('happened_at', 'N/A')[:19]
            intent = msg.get('intent_label') or 'none'
            template = msg.get('template_slug') or 'none'
            text = (msg.get('message_text') or '')[:60]
            
            print(f"\n{i}. {direction_icon} {direction.upper()} | {happened_at}")
            print(f"   Intent: {intent} | Template: {template}")
            print(f"   Text: {text}")
        
        print("\n" + "=" * 100 + "\n")
    
    except Exception as e:
        print(f"❌ Error fetching messages: {e}")
        sys.exit(1)


def list_appts(agreement: str):
    """Show appointments for an agreement."""
    from tools import get_client, resolve_agreement_id
    
    try:
        client = get_client()
        agreement_id = resolve_agreement_id(agreement)
        
        if not agreement_id:
            print(f"❌ Agreement {agreement} not found")
            sys.exit(1)
        
        # Get appointments
        result = client.table('appointment_request') \
            .select('*') \
            .eq('agreement_id', agreement_id) \
            .order('created_at', desc=True) \
            .execute()
        
        if not result.data:
            print(f"📭 No appointments found for {agreement}")
            return
        
        print(f"\n📅 APPOINTMENTS ({agreement})")
        print("=" * 100)
        
        for i, appt in enumerate(result.data, 1):
            appt_id = appt.get('id', 'N/A')
            status = appt.get('status', 'N/A')
            requested_by = appt.get('requested_by', 'N/A')
            channel = appt.get('channel', 'N/A')
            pref_date = appt.get('preferred_date') or 'not set'
            pref_time = appt.get('preferred_time') or 'not set'
            notes = appt.get('notes', '')[:50]
            created = appt.get('created_at', 'N/A')[:19]
            
            print(f"\n{i}. Appointment ID: {appt_id}")
            print(f"   Status: {status} | Requested by: {requested_by} | Channel: {channel}")
            print(f"   Preferred: {pref_date} at {pref_time}")
            print(f"   Notes: {notes}")
            print(f"   Created: {created}")
        
        print("\n" + "=" * 100 + "\n")
    
    except Exception as e:
        print(f"❌ Error fetching appointments: {e}")
        sys.exit(1)


def seed_deferral(text: str):
    """Seed a test inbound deferral message."""
    from tools import log_message
    
    # Get test agreement number from env or use default
    test_agreement = os.getenv('TEST_AGN', '0000440141796331')
    
    try:
        # Log inbound message
        log_message(
            agreement_ref=test_agreement,
            channel='whatsapp',
            direction='inbound',
            message_text=text,
            intent_label='test_deferral',
            template_slug=None,
            source='test',
            model=None
        )
        
        print(f"\n✅ Seeded inbound deferral")
        print(f"   Agreement: {test_agreement}")
        print(f"   Text: '{text}'")
        print(f"   Channel: whatsapp")
        print(f"\n💡 Tip: Let Android_Handler_Live poll (60s) to process this message\n")
    
    except Exception as e:
        print(f"❌ Error seeding deferral: {e}")
        sys.exit(1)


def cmd_resume_comms(agreement_number: str):
    """Resume outbound communications for an agreement."""
    client = get_supabase()
    
    try:
        # Call the Postgres function via RPC
        result = client.rpc('fn_mgr_resume_comms', {
            'p_agreement_number': agreement_number
        }).execute()
        
        if not result.data:
            print(f"❌ No response from database")
            sys.exit(1)
        
        response = result.data
        
        # Check if response is a dict with 'ok' field
        if isinstance(response, dict):
            if response.get('ok') is True:
                print(f"✅ Comms resumed for {agreement_number}")
            elif response.get('ok') is False and response.get('error') == 'agreement_not_found':
                print(f"❌ Agreement not found: {agreement_number}")
            else:
                # Print raw response for debugging
                import json
                print(f"⚠️  Unexpected response:")
                print(json.dumps(response, indent=2))
        else:
            # If response is not a dict, print it as-is
            import json
            print(f"Response:")
            print(json.dumps(response, indent=2))
        
    except Exception as e:
        print(f"❌ Error resuming comms: {e}")
        sys.exit(1)


def cmd_dealt(agreement_number: str):
    """Mark an agreement as dealt (customer purchased) and pause comms."""
    client = get_supabase()

    try:
        result = client.rpc('fn_mgr_dealt', {
            'p_agreement_number': agreement_number
        }).execute()

        if not result.data:
            print("❌ No response from database")
            sys.exit(1)

        response = result.data

        # Normal expected shape: {"ok": true/false, "action": "...", "agreement_number": "..."}
        if isinstance(response, dict):
            if response.get('ok') is True:
                action = response.get('action') or 'dealt'
                print(f"✅ Customer marked as {action} for {agreement_number}")
                print("🔕 Outbound comms have been paused for this agreement.")
            elif response.get('ok') is False and response.get('error') == 'agreement_not_found':
                print(f"❌ Agreement not found: {agreement_number}")
                sys.exit(1)
            else:
                import json
                print("⚠️ Unexpected response from fn_mgr_dealt:")
                print(json.dumps(response, indent=2))
                sys.exit(1)
        else:
            # Fallback: print raw data if it's not a dict
            import json
            print("⚠️ Unexpected response format from fn_mgr_dealt:")
            print(json.dumps(response, indent=2))
            sys.exit(1)

    except Exception as e:
        print(f"❌ Error marking as dealt: {e}")
        sys.exit(1)


def tcard_view(agreement_number: str):
    """Display T-Card summary for one customer agreement."""
    client = get_supabase()
    
    try:
        # 1. Get summary from v_tcard_summary
        summary_result = client.table('v_tcard_summary') \
            .select('customer_name, registration, model, asset_type, end_date, monthly_payment, true_equity, equity_flag, next_followup_at, last_lost_reason_label') \
            .eq('agreement_number', agreement_number) \
            .execute()
        
        if not summary_result.data:
            print(f"❌ No record found for agreement number: {agreement_number}")
            sys.exit(1)
        
        summary = summary_result.data[0]
        
        # Print summary section
        print("\n📇 T-CARD SUMMARY")
        print("─" * 60)
        print(f"Customer:       {summary.get('customer_name') or '—'}")
        print(f"Vehicle:        {summary.get('model') or '—'} ({summary.get('registration') or '—'})")
        print(f"Asset Type:     {summary.get('asset_type') or '—'}")
        print(f"Agreement End:  {summary.get('end_date') or '—'}")
        print(f"Payment:        £{summary.get('monthly_payment') or '0.00'}")
        
        # Format equity with flag color indicator
        equity = summary.get('true_equity')
        equity_flag = summary.get('equity_flag') or 'none'
        equity_str = f"£{equity}" if equity else '—'
        print(f"Equity:         {equity_str} [{equity_flag}]")
        
        print(f"Next Follow-Up: {summary.get('next_followup_at') or '—'}")
        print(f"Lost Reason:    {summary.get('last_lost_reason_label') or '—'}")
        
        # 2. Get appointments from v_tcard_appointments
        appts_result = client.table('v_tcard_appointments') \
            .select('preferred_date, preferred_time, status, reminder_channel, thanks_needed') \
            .eq('agreement_number', agreement_number) \
            .order('created_at', desc=True) \
            .execute()
        
        print("\n📅 APPOINTMENTS")
        print("─" * 60)
        
        if not appts_result.data:
            print("No appointments found.")
        else:
            print(f"{'Date':<12} {'Time':<8} {'Status':<10} {'Reminder':<10} {'Thanks'}")
            print("─" * 60)
            for appt in appts_result.data:
                date = appt.get('preferred_date') or '—'
                time = appt.get('preferred_time') or '—'
                status = appt.get('status') or '—'
                reminder = appt.get('reminder_channel') or '—'
                thanks = str(appt.get('thanks_needed', '—'))
                print(f"{date:<12} {time:<8} {status:<10} {reminder:<10} {thanks}")
        
        # 3. Get recent messages from v_tcard_contact_history
        msgs_result = client.table('v_tcard_contact_history') \
            .select('happened_at, direction, message_text') \
            .eq('agreement_number', agreement_number) \
            .order('happened_at', desc=True) \
            .limit(15) \
            .execute()
        
        print("\n💬 RECENT MESSAGES")
        print("─" * 60)
        
        if not msgs_result.data:
            print("No messages found.")
        else:
            for msg in msgs_result.data:
                happened = msg.get('happened_at', '—')[:16]  # YYYY-MM-DD HH:MM
                direction_arrow = '→' if msg.get('direction') == 'outbound' else '←'
                text = msg.get('message_text') or ''
                # Truncate and clean text
                text = text.replace('\n', ' ').replace('\r', ' ')[:100]
                print(f"{happened} {direction_arrow} {text}")
        
        print("\n" + "─" * 60 + "\n")
    
    except Exception as e:
        print(f"❌ Error fetching T-Card data: {e}")
        sys.exit(1)


def main():
    """Main CLI entry point."""
    parser = argparse.ArgumentParser(
        description='Follow-up Manager CLI',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog="""
Examples:
  %(prog)s list_due --days 21
  %(prog)s done --id 123 --note "Called and closed"
  %(prog)s resched --id 123 --at "2025-12-15 09:00"
  %(prog)s nudge --id 123 --channel whatsapp --tag "Offer-Refresh-Dec"
        """
    )
    
    subparsers = parser.add_subparsers(dest='command', help='Command to run')
    
    # list_due command
    list_parser = subparsers.add_parser('list_due', help='List follow-ups due soon')
    list_parser.add_argument('--days', type=int, default=21, help='Number of days to look ahead (default: 21)')
    
    # done command
    done_parser = subparsers.add_parser('done', help='Mark a follow-up as done')
    done_parser.add_argument('--id', type=int, required=True, help='Follow-up ID')
    done_parser.add_argument('--note', type=str, help='Optional note (e.g., "Called and closed")')
    
    # resched command
    resched_parser = subparsers.add_parser('resched', help='Reschedule a follow-up')
    resched_parser.add_argument('--id', type=int, required=True, help='Follow-up ID')
    resched_parser.add_argument('--at', type=str, required=True, help='New date/time in UK time (YYYY-MM-DD HH:MM)')
    
    # nudge command
    nudge_parser = subparsers.add_parser('nudge', help='Queue a nudge from a follow-up')
    nudge_parser.add_argument('--id', type=int, required=True, help='Follow-up ID')
    nudge_parser.add_argument('--channel', type=str, default='whatsapp', choices=['whatsapp', 'sms', 'email'], help='Channel (default: whatsapp)')
    nudge_parser.add_argument('--tag', type=str, help='Campaign tag (e.g., "Offer-Refresh-Dec")')
    
    # open_thread command
    open_parser = subparsers.add_parser('open_thread', help='Open a thread for an agreement')
    open_parser.add_argument('--agreement', type=str, required=True, help='Agreement number')
    open_parser.add_argument('--type', type=str, default='renewal', choices=['renewal', 'service', 'general'], help='Thread type (default: renewal)')
    
    # seed_inbound command
    seed_inbound_parser = subparsers.add_parser('seed_inbound', help='Seed an inbound message')
    seed_inbound_parser.add_argument('--agreement', type=str, required=True, help='Agreement number')
    seed_inbound_parser.add_argument('--channel', type=str, default='whatsapp', choices=['whatsapp', 'sms', 'email'], help='Channel (default: whatsapp)')
    seed_inbound_parser.add_argument('--text', type=str, required=True, help='Message text')
    
    # recent_msgs command
    msgs_parser = subparsers.add_parser('recent_msgs', help='Show recent messages for an agreement')
    msgs_parser.add_argument('--agreement', type=str, required=True, help='Agreement number')
    msgs_parser.add_argument('--limit', type=int, default=10, help='Number of messages to show (default: 10)')
    
    # appts command
    appts_parser = subparsers.add_parser('appts', help='Show appointments for an agreement')
    appts_parser.add_argument('--agreement', type=str, required=True, help='Agreement number')
    
    # seed_deferral command (test only)
    seed_parser = subparsers.add_parser('seed_deferral', help='Seed a test inbound deferral message')
    seed_parser.add_argument('--text', type=str, required=True, help='Deferral text (e.g., "after Christmas")')
    
    # tcard command
    tcard_parser = subparsers.add_parser('tcard', help='Display T-Card summary for one customer agreement')
    tcard_parser.add_argument('--agreement-number', type=str, required=True, help='Agreement number (e.g., 0000440141796331)')
    
    # resume_comms command
    resume_comms_parser = subparsers.add_parser('resume_comms', help='Resume outbound comms for an agreement')
    resume_comms_parser.add_argument('--agreement-number', type=str, required=True, help='VWFS agreement number')
    
    # dealt command
    dealt_parser = subparsers.add_parser('dealt', help='Mark agreement as dealt (customer purchased) and pause comms')
    dealt_parser.add_argument('--agreement-number', type=str, required=True, help='VWFS agreement number')
    
    args = parser.parse_args()
    
    if not args.command:
        parser.print_help()
        sys.exit(1)
    
    # Execute command
    if args.command == 'list_due':
        list_due(args.days)
    elif args.command == 'done':
        mark_done(args.id, args.note)
    elif args.command == 'resched':
        reschedule(args.id, args.at)
    elif args.command == 'nudge':
        queue_nudge(args.id, args.channel, args.tag)
    elif args.command == 'open_thread':
        open_thread(args.agreement, args.type)
    elif args.command == 'seed_inbound':
        seed_inbound(args.agreement, args.channel, args.text)
    elif args.command == 'recent_msgs':
        recent_msgs(args.agreement, args.limit)
    elif args.command == 'appts':
        list_appts(args.agreement)
    elif args.command == 'seed_deferral':
        seed_deferral(args.text)
    elif args.command == 'tcard':
        tcard_view(args.agreement_number)
    elif args.command == 'resume_comms':
        cmd_resume_comms(args.agreement_number)
    elif args.command == 'dealt':
        cmd_dealt(args.agreement_number)


if __name__ == '__main__':
    main()
