#!/usr/bin/env python3
"""
Complete LiveKit Telephony Setup
This script sets up everything needed for Twilio → LiveKit → Agent calls
"""
import asyncio
import os
import sys
from dotenv import load_dotenv
from livekit import api

# Load environment variables
load_dotenv(".env.local")

class TelephonySetup:
    def __init__(self):
        self.livekit_url = os.getenv("LIVEKIT_URL")
        self.livekit_key = os.getenv("LIVEKIT_API_KEY")
        self.livekit_secret = os.getenv("LIVEKIT_API_SECRET")
        self.twilio_phone = os.getenv("TWILIO_PHONE_NUMBER")
        
        if not all([self.livekit_url, self.livekit_key, self.livekit_secret, self.twilio_phone]):
            print("❌ Missing required environment variables in .env.local:")
            if not self.livekit_url:
                print("   - LIVEKIT_URL")
            if not self.livekit_key:
                print("   - LIVEKIT_API_KEY")
            if not self.livekit_secret:
                print("   - LIVEKIT_API_SECRET")
            if not self.twilio_phone:
                print("   - TWILIO_PHONE_NUMBER")
            sys.exit(1)
        
        self.livekit_api = api.LiveKitAPI(
            url=self.livekit_url,
            api_key=self.livekit_key,
            api_secret=self.livekit_secret
        )
    
    async def check_existing_setup(self):
        """Check what's already configured"""
        print("\n🔍 Checking existing configuration...")
        
        try:
            # Check inbound trunks
            trunks = await self.livekit_api.sip.list_inbound_trunk(
                api.ListSIPInboundTrunkRequest()
            )
            
            trunk_exists = False
            trunk_id = None
            for trunk in trunks.items:
                if self.twilio_phone in trunk.numbers:
                    trunk_exists = True
                    trunk_id = trunk.sip_trunk_id
                    print(f"   ✅ Inbound trunk exists: {trunk.name} (ID: {trunk_id})")
                    break
            
            if not trunk_exists:
                print(f"   ❌ No inbound trunk found for {self.twilio_phone}")
            
            # Check dispatch rules
            rules = await self.livekit_api.sip.list_dispatch_rule(
                api.ListSIPDispatchRuleRequest()
            )
            
            rule_exists = False
            if trunk_id:
                for rule in rules.items:
                    if trunk_id in rule.trunk_ids:
                        rule_exists = True
                        print(f"   ✅ Dispatch rule exists: {rule.name}")
                        break
            
            if not rule_exists:
                print(f"   ❌ No dispatch rule found")
            
            return trunk_exists, rule_exists, trunk_id
            
        except Exception as e:
            print(f"   ❌ Error checking configuration: {e}")
            return False, False, None
    
    async def create_inbound_trunk(self):
        """Create inbound SIP trunk"""
        print(f"\n📞 Creating inbound SIP trunk for {self.twilio_phone}...")
        
        try:
            request = api.CreateSIPInboundTrunkRequest(
                name="Twilio Inbound",
                numbers=[self.twilio_phone],
                krisp_enabled=True,
            )
            
            result = await self.livekit_api.sip.create_inbound_trunk(request)
            
            print(f"   ✅ Trunk created: {result.name}")
            print(f"   📋 Trunk ID: {result.sip_trunk_id}")
            return result.sip_trunk_id
            
        except Exception as e:
            if "already exists" in str(e).lower():
                print(f"   ℹ️  Trunk already exists")
                # Get the existing trunk ID
                trunks = await self.livekit_api.sip.list_inbound_trunk(
                    api.ListSIPInboundTrunkRequest()
                )
                for trunk in trunks.items:
                    if self.twilio_phone in trunk.numbers:
                        return trunk.sip_trunk_id
            else:
                print(f"   ❌ Error: {e}")
                return None
    
    async def create_dispatch_rule(self, trunk_id):
        """Create dispatch rule"""
        print(f"\n🎯 Creating dispatch rule...")
        
        try:
            # Create dispatch rule with direct routing
            request = api.CreateSIPDispatchRuleRequest(
                name="Twilio to Agent",
                trunk_ids=[trunk_id],
                rule=api.SIPDispatchRule(
                    dispatch_rule_direct=api.SIPDispatchRuleDirect(
                        room_name="",
                        pin="",
                    )
                ),
                attributes={
                    "agent_name": "default",
                }
            )
            
            result = await self.livekit_api.sip.create_dispatch_rule(request)
            
            print(f"   ✅ Rule created: {result.name}")
            print(f"   📋 Rule ID: {result.sip_dispatch_rule_id}")
            return True
            
        except Exception as e:
            if "already exists" in str(e).lower():
                print(f"   ℹ️  Dispatch rule already exists")
                return True
            else:
                print(f"   ❌ Error: {e}")
                return False
    
    async def setup(self):
        """Run complete setup"""
        print("=" * 70)
        print("🚀 LiveKit Telephony Setup for Twilio")
        print("=" * 70)
        print(f"\n📱 Phone Number: {self.twilio_phone}")
        print(f"🌐 LiveKit URL: {self.livekit_url}")
        
        # Check existing setup
        trunk_exists, rule_exists, trunk_id = await self.check_existing_setup()
        
        # Create trunk if needed
        if not trunk_exists:
            trunk_id = await self.create_inbound_trunk()
            if not trunk_id:
                print("\n❌ Failed to create inbound trunk. Aborting.")
                return False
        
        # Create dispatch rule if needed
        if not rule_exists:
            success = await self.create_dispatch_rule(trunk_id)
            if not success:
                print("\n❌ Failed to create dispatch rule. Aborting.")
                return False
        
        # Summary
        print("\n" + "=" * 70)
        print("✅ Setup Complete!")
        print("=" * 70)
        
        if trunk_exists and rule_exists:
            print("\n✨ Everything was already configured!")
        else:
            print("\n📋 What was configured:")
            if not trunk_exists:
                print("   ✅ Inbound SIP trunk created")
            if not rule_exists:
                print("   ✅ Dispatch rule created")
        
        print("\n🎯 Next Steps:")
        print("   1. Start your agent:")
        print("      cd /var/www/html/vikas/2025-Nov-21-Voicebot/BackEnd/agent-starter-python")
        print("      python3 -m src.agent")
        print(f"\n   2. Call your number: {self.twilio_phone}")
        print("\n   3. The agent should answer! 🎉")
        
        print("\n📚 For more info, see: TELEPHONY_SETUP.md")
        print("=" * 70)
        
        return True
    
    async def close(self):
        """Close API connection"""
        await self.livekit_api.aclose()

async def main():
    setup = TelephonySetup()
    try:
        await setup.setup()
    finally:
        await setup.close()

if __name__ == "__main__":
    asyncio.run(main())
