
# CrewAI + Twilio Conversations WhatsApp Customer Support Automation
# Complete implementation example

import os
from crewai import Crew, Agent, Task, LLM
from crewai_tools import BaseTool
from twilio.rest import Client
from flask import Flask, request, jsonify
from typing import Optional, Dict, Any
import json
import logging

# ================================
# 1. CONFIGURATION
# ================================

class Config:
    # Twilio Configuration
    TWILIO_ACCOUNT_SID = os.getenv('TWILIO_ACCOUNT_SID')
    TWILIO_AUTH_TOKEN = os.getenv('TWILIO_AUTH_TOKEN')
    TWILIO_WHATSAPP_NUMBER = os.getenv('TWILIO_WHATSAPP_NUMBER')  # e.g., '+14155238886'

    # OpenAI Configuration for CrewAI
    OPENAI_API_KEY = os.getenv('OPENAI_API_KEY')

    # Webhook Configuration
    WEBHOOK_BASE_URL = os.getenv('WEBHOOK_BASE_URL')  # Your public URL

# ================================
# 2. TWILIO SERVICE
# ================================

class TwilioService:
    def __init__(self):
        self.client = Client(Config.TWILIO_ACCOUNT_SID, Config.TWILIO_AUTH_TOKEN)

    def send_whatsapp_message(self, to: str, message: str) -> bool:
        try:
            self.client.messages.create(
                body=message,
                from_=f'whatsapp:{Config.TWILIO_WHATSAPP_NUMBER}',
                to=f'whatsapp:{to}'
            )
            return True
        except Exception as e:
            logging.error(f"Failed to send WhatsApp message: {e}")
            return False

    def create_conversation(self, friendly_name: str) -> Optional[str]:
        try:
            conversation = self.client.conversations.v1.conversations.create(
                friendly_name=friendly_name
            )
            return conversation.sid
        except Exception as e:
            logging.error(f"Failed to create conversation: {e}")
            return None

# ================================
# 3. CUSTOM TOOLS FOR CREWAI
# ================================

class CustomerDataTool(BaseTool):
    name: str = "Customer Data Lookup"
    description: str = "Retrieve customer information from database"

    def _run(self, customer_phone: str) -> str:
        # Simulate customer data lookup
        customer_data = {
            "+1234567890": {
                "name": "John Doe",
                "email": "john@example.com",
                "order_history": ["Order #12345", "Order #12346"],
                "last_contact": "2024-12-01",
                "tier": "Premium"
            }
        }

        if customer_phone in customer_data:
            return json.dumps(customer_data[customer_phone])
        return "Customer not found in database"

class KnowledgeBaseTool(BaseTool):
    name: str = "Knowledge Base Search"
    description: str = "Search company knowledge base for answers"

    def _run(self, query: str) -> str:
        # Simulate knowledge base search
        knowledge_base = {
            "refund": "Refunds are processed within 5-7 business days.",
            "shipping": "Standard shipping takes 3-5 business days.",
            "return": "Items can be returned within 30 days of purchase.",
            "account": "Access your account at our website."
        }

        for key, value in knowledge_base.items():
            if key.lower() in query.lower():
                return value

        return "Please contact our human support team for more help."

# ================================
# 4. CREWAI AGENTS SETUP
# ================================

class CustomerSupportCrew:
    def __init__(self):
        self.llm = LLM(
            model="gpt-4",
            api_key=Config.OPENAI_API_KEY,
            temperature=0.3
        )

        # Initialize tools
        self.customer_data_tool = CustomerDataTool()
        self.knowledge_base_tool = KnowledgeBaseTool()

        # Create agents
        self.support_agent = Agent(
            role="Customer Support Representative",
            goal="Provide helpful, accurate, and friendly customer support",
            backstory="You are an experienced customer support representative.",
            tools=[self.customer_data_tool, self.knowledge_base_tool],
            llm=self.llm
        )

        self.quality_agent = Agent(
            role="Quality Assurance Specialist", 
            goal="Ensure responses meet quality standards",
            backstory="You review support interactions for quality.",
            llm=self.llm
        )

    def handle_customer_query(self, customer_phone: str, message: str) -> str:
        # Create tasks for the crew
        support_task = Task(
            description=f"Handle customer inquiry from {customer_phone}: {message}",
            agent=self.support_agent,
            expected_output="A helpful response to the customer"
        )

        quality_task = Task(
            description="Review the support response for quality",
            agent=self.quality_agent,
            expected_output="Quality-assured response",
            context=[support_task]
        )

        # Create and execute the crew
        crew = Crew(
            agents=[self.support_agent, self.quality_agent],
            tasks=[support_task, quality_task]
        )

        result = crew.kickoff()
        return str(result)

# ================================
# 5. FLASK WEBHOOK APPLICATION  
# ================================

app = Flask(__name__)
twilio_service = TwilioService()
support_crew = CustomerSupportCrew()

@app.route('/webhook/whatsapp', methods=['POST'])
def whatsapp_webhook():
    try:
        from_number = request.form.get('From', '').replace('whatsapp:', '')
        message_body = request.form.get('Body', '')

        # Handle with CrewAI
        ai_response = support_crew.handle_customer_query(from_number, message_body)

        # Send response
        success = twilio_service.send_whatsapp_message(from_number, ai_response)

        return jsonify({"status": "success" if success else "error"}), 200

    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)
