#!/usr/bin/env python3
"""
Direct API Lead Creator for Wright Choice HS
This script creates Lead DocTypes directly via ERPNext API
"""

import requests
import json
import sys
import os
from datetime import datetime
import urllib3

# Disable SSL warnings for self-signed certificates
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)

# ERPNext API Configuration
ERPNEXT_URL = "https://portal.wrightchoicehs.com:5750"  # Update with your ERPNext URL
API_KEY = ""  # Will be set from environment variable
API_SECRET = ""  # Will be set from environment variable

def load_api_credentials():
    """Load API credentials from environment variables"""
    global API_KEY, API_SECRET
    API_KEY = os.getenv('ERPNEXT_API_KEY')
    API_SECRET = os.getenv('ERPNEXT_API_SECRET')
    
    if not API_KEY or not API_SECRET:
        print("ERROR: ERPNEXT_API_KEY and ERPNEXT_API_SECRET environment variables must be set")
        print("Please set these environment variables:")
        print("export ERPNEXT_API_KEY=your_api_key")
        print("export ERPNEXT_API_SECRET=your_api_secret")
        sys.exit(1)

def get_auth_headers():
    """Get authentication headers with proper token format"""
    token = f"{API_KEY}:{API_SECRET}"
    return {
        "Authorization": f"token {token}",
        "Accept": "application/json",
        "Content-Type": "application/json"
    }

def test_authentication():
    """Test authentication with ERPNext API"""
    try:
        response = requests.get(
            f"{ERPNEXT_URL}/api/method/frappe.auth.get_logged_user",
            headers=get_auth_headers(),
            verify=False,
            timeout=10
        )
        
        if response.status_code == 200:
            data = response.json()
            print(f"✅ Authentication successful - User: {data.get('message', 'Unknown')}")
            return True
        else:
            print(f"❌ Authentication failed: {response.status_code} - {response.text}")
            return False
            
    except Exception as e:
        print(f"❌ Authentication error: {str(e)}")
        return False

def create_contact_via_api(full_name, email, phone, contact_type=None):
    """Create or update a Contact via ERPNext API"""
    try:
        # Check if contact already exists by email
        if email:
            response = requests.get(
                f"{ERPNEXT_URL}/api/resource/Contact",
                params={"filters": json.dumps({"email_ids.email_id": email.lower().strip()})},
                headers=get_auth_headers(),
                verify=False
            )
            
            if response.status_code == 200:
                existing_contacts = response.json().get('data', [])
                if existing_contacts:
                    # Contact exists, return the Contact name
                    contact_name = existing_contacts[0].get('name')
                    print(f"ℹ️ Found existing Contact: {contact_name}")
                    return contact_name
        
        # Create new contact
        name_parts = full_name.strip().split(" ", 1)
        first_name = name_parts[0] if name_parts else ""
        last_name = name_parts[1] if len(name_parts) > 1 else ""
        
        contact_data = {
            "full_name": full_name,
            "first_name": first_name,
            "last_name": last_name
        }
        
        # Add email if provided
        if email:
            contact_data["email_ids"] = [{"email_id": email.lower().strip(), "is_primary": 1}]
        
        # Add phone if provided
        if phone:
            contact_data["phone_nos"] = [{"phone": phone, "is_primary_mobile_no": 1}]
        
        # Add custom contact type if provided
        if contact_type:
            # Ensure we only use the exact values that ERPNext accepts
            if contact_type in ["Referral Source", "Referral"]:
                contact_data["custom_contact_type"] = contact_type
            else:
                print(f"⚠️ Invalid contact type '{contact_type}', skipping")
        
        response = requests.post(
            f"{ERPNEXT_URL}/api/resource/Contact",
            json=contact_data,
            headers=get_auth_headers(),
            verify=False
        )
        
        if response.status_code in [200, 201]:
            contact_name = response.json().get('data', {}).get('name')
            print(f"✅ Created new Contact: {contact_name} (Type: {contact_type or 'None'})")
            return contact_name
        else:
            print(f"❌ Failed to create Contact: {response.status_code} - {response.text}")
            return None
            
    except Exception as e:
        print(f"❌ Error creating Contact: {str(e)}")
        return None

def link_contact_to_lead(contact_name, lead_name):
    """Link a Contact to a Lead via API"""
    try:
        # Get the contact document
        response = requests.get(
            f"{ERPNEXT_URL}/api/resource/Contact/{contact_name}",
            headers=get_auth_headers(),
            verify=False
        )
        
        if response.status_code != 200:
            print(f"❌ Failed to get Contact {contact_name}: {response.status_code}")
            return
            
        contact_doc = response.json().get('data', {})
        
        # Check if link already exists
        existing_links = contact_doc.get('links', [])
        for link in existing_links:
            if link.get('link_doctype') == 'Lead' and link.get('link_name') == lead_name:
                print(f"ℹ️ Contact {contact_name} already linked to Lead {lead_name}")
                return
        
        # Add new link
        if 'links' not in contact_doc:
            contact_doc['links'] = []
        contact_doc['links'].append({
            "link_doctype": "Lead",
            "link_name": lead_name
        })
        
        # Update the contact
        response = requests.put(
            f"{ERPNEXT_URL}/api/resource/Contact/{contact_name}",
            json=contact_doc,
            headers=get_auth_headers(),
            verify=False
        )
        
        if response.status_code == 200:
            print(f"✅ Linked Contact {contact_name} to Lead {lead_name}")
        else:
            print(f"❌ Failed to link Contact to Lead: {response.status_code} - {response.text}")
            
    except Exception as e:
        print(f"❌ Error linking Contact to Lead: {str(e)}")

def add_comment_to_lead(lead_name, lead_data):
    """Add a comment/note to a Lead for referral information"""
    try:
        comment_text = ""
        inquiry = lead_data.get('inquiry', '')
        
        # For referral inquiries, the comment should show who made the referral (original submitter)
        if inquiry == 'referral':
            referral_parts = []
            if lead_data.get('first_name') and lead_data.get('last_name'):
                referral_parts.append(f"Name: {lead_data.get('first_name')} {lead_data.get('last_name')}")
            if lead_data.get('mobile_no'):
                referral_parts.append(f"Phone: {lead_data.get('mobile_no')}")
            if lead_data.get('email'):
                referral_parts.append(f"Email: {lead_data.get('email')}")
            
            if referral_parts:
                comment_text = f"Referred by: {' | '.join(referral_parts)}"
        else:
            # For non-referral inquiries, show referral information if provided
            referral_parts = []
            if lead_data.get('ref_first_name') and lead_data.get('ref_last_name'):
                referral_parts.append(f"Name: {lead_data.get('ref_first_name')} {lead_data.get('ref_last_name')}")
            if lead_data.get('ref_phone'):
                referral_parts.append(f"Phone: {lead_data.get('ref_phone')}")
            if lead_data.get('ref_email'):
                referral_parts.append(f"Email: {lead_data.get('ref_email')}")
            
            if referral_parts:
                comment_text = f"Referral from: {' | '.join(referral_parts)}"
        
        if comment_text:
            comment_data = {
                "reference_doctype": "Lead",
                "reference_name": lead_name,
                "content": comment_text,
                "comment_type": "Comment"
            }
            
            response = requests.post(
                f"{ERPNEXT_URL}/api/resource/Comment",
                json=comment_data,
                headers=get_auth_headers(),
                verify=False
            )
            
            if response.status_code in [200, 201]:
                print(f"✅ Added referral comment to Lead {lead_name}")
            else:
                print(f"⚠️ Failed to add comment to Lead: {response.status_code} - {response.text}")
                
    except Exception as e:
        print(f"❌ Error adding comment to Lead: {str(e)}")

def check_duplicate_lead(email, inquiry):
    """Check if a lead already exists for this email and inquiry type"""
    try:
        response = requests.get(
            f"{ERPNEXT_URL}/api/resource/Lead",
            params={"filters": json.dumps({"email_id": email})},
            headers=get_auth_headers(),
            verify=False
        )
        
        if response.status_code == 200:
            existing_leads = response.json().get('data', [])
            return len(existing_leads) > 0
        return False
        
    except Exception as e:
        print(f"❌ Error checking for duplicate lead: {str(e)}")
        return False

def create_lead_via_api(lead_data):
    """Create a Lead via ERPNext API"""
    try:
        # Validate required fields
        if not lead_data.get('email'):
            print("❌ Email is required")
            return None
            
        inquiry = lead_data.get('inquiry', '')
        
        # If this is a referral inquiry, swap the main and referral data
        if inquiry == 'referral':
            # Use referral data as the main lead data
            first_name = lead_data.get('ref_first_name', '').strip()
            last_name = lead_data.get('ref_last_name', '').strip()
            email = lead_data.get('ref_email', '').lower().strip()
            phone = lead_data.get('ref_phone', '').strip()
            
            # Store original submitter data for custom fields
            original_first_name = lead_data.get('first_name', '').strip()
            original_last_name = lead_data.get('last_name', '').strip()
            original_email = lead_data.get('email', '').lower().strip()
            original_phone = lead_data.get('mobile_no', '').strip()
        else:
            # Use normal data structure
            first_name = lead_data.get('first_name', '').strip()
            last_name = lead_data.get('last_name', '').strip()
            email = lead_data.get('email', '').lower().strip()
            phone = lead_data.get('mobile_no', '').strip()
            original_first_name = original_last_name = original_email = original_phone = None
        
        if not first_name:
            print("❌ First name is required")
            return None
        
        # Check for duplicate
        if check_duplicate_lead(email, inquiry):
            print(f"⏭️ Duplicate lead exists for {email} with inquiry {inquiry}")
            return None
        
        # Map inquiry types to ERPNext valid values for custom_inquiry_type field
        inquiry_mapping = {
            "general": "General Question",
            "referral": "Client Referral", 
            "service": "Service Inquiry",
            "other": "Other"
        }
        
        # Map preferred contact method options to custom field values
        preferred_contact_mapping = {
            "Phone Call": "Phone Call",
            "Email": "Email", 
            "Text Message": "Text Message"
        }
        
        # Prepare Lead data with required fields
        lead_doc_data = {
            "first_name": first_name,
            "last_name": last_name,
            "lead_name": f"{first_name} {last_name}",
            "email_id": email,
            "status": "Lead"
        }
        
        # Add optional fields if provided
        if phone:
            lead_doc_data["mobile_no"] = phone
        
        # Add service area as territory
        if lead_data.get('service_area'):
            lead_doc_data["territory"] = lead_data.get('service_area')
        
        # Add custom referral fields if this is a referral inquiry
        if inquiry == 'referral' and original_first_name:
            lead_doc_data["custom_referral_first_name"] = original_first_name
            if original_last_name:
                lead_doc_data["custom_referral_last_name"] = original_last_name
            if original_email:
                lead_doc_data["custom_referral_email"] = original_email
            if original_phone:
                lead_doc_data["custom_referral_phone"] = original_phone
        
        # Add message to custom_message field (check both field names)
        message = lead_data.get('message') or lead_data.get('custom_message')
        if message:
            lead_doc_data["custom_message"] = message
        
        # Map preferred contact method to custom field
        preferred_contact = lead_data.get('source', '')
        if preferred_contact in preferred_contact_mapping:
            lead_doc_data["custom_preferred_contact_method"] = preferred_contact_mapping[preferred_contact]
        
        # Set default Lead Source since we're no longer using source for contact method
        lead_doc_data["source"] = "Website"
        
        # Set mandatory custom fields
        lead_doc_data["custom_referral_date"] = datetime.now().strftime("%Y-%m-%d")
        lead_doc_data["custom_client_type"] = ""  # Valid values: Individual, Family, Organization
        
        # Note: Removed company_name setting for service inquiries as it overrides lead display name
        
        # Set custom_inquiry_type field based on inquiry
        if inquiry in inquiry_mapping:
            lead_doc_data["custom_inquiry_type"] = inquiry_mapping[inquiry]
        
        # Create the Lead
        response = requests.post(
            f"{ERPNEXT_URL}/api/resource/Lead",
            json=lead_doc_data,
            headers=get_auth_headers(),
            verify=False
        )
        
        if response.status_code in [200, 201]:
            lead_name = response.json().get('data', {}).get('name')
            print(f"✅ Created Lead: {lead_name}")
            
            # Add comment/note if referral information is provided
            if inquiry == 'referral' or ((lead_data.get('ref_first_name') and lead_data.get('ref_last_name')) or lead_data.get('ref_phone') or lead_data.get('ref_email')):
                add_comment_to_lead(lead_name, lead_data)
            
            # Create contacts for referral inquiries
            if inquiry == 'referral':
                # Find and update the auto-created contact for the referred person
                try:
                    import time
                    
                    # Try multiple times to find the auto-created contact
                    for attempt in range(3):
                        time.sleep(1)  # Wait for ERPNext to create the contact
                        
                        # Find the auto-created contact by name (email search sometimes fails with 500 error)
                        full_name = f"{first_name} {last_name}".strip()
                        response = requests.get(
                            f"{ERPNEXT_URL}/api/resource/Contact",
                            params={"filters": json.dumps({"full_name": full_name})},
                            headers=get_auth_headers(),
                            verify=False
                        )
                        
                        if response.status_code == 200:
                            existing_contacts = response.json().get('data', [])
                            if existing_contacts:
                                contact = existing_contacts[0]  # Get the first matching contact
                                contact_name = contact.get('name')
                                
                                # Get the full contact details first
                                get_response = requests.get(
                                    f"{ERPNEXT_URL}/api/resource/Contact/{contact_name}",
                                    headers=get_auth_headers(),
                                    verify=False
                                )
                                
                                if get_response.status_code == 200:
                                    contact_doc = get_response.json().get('data', {})
                                    contact_doc["custom_contact_type"] = "Referral"
                                    
                                    # Update the contact
                                    update_response = requests.put(
                                        f"{ERPNEXT_URL}/api/resource/Contact/{contact_name}",
                                        json=contact_doc,
                                        headers=get_auth_headers(),
                                        verify=False
                                    )
                                    
                                    if update_response.status_code == 200:
                                        print(f"✅ Updated Contact {contact_name} type to Referral")
                                        break
                                    else:
                                        print(f"⚠️ Failed to update Contact {contact_name}: {update_response.status_code} - {update_response.text}")
                                else:
                                    print(f"⚠️ Failed to get Contact {contact_name}: {get_response.status_code}")
                            else:
                                print(f"⚠️ No contact found for email {email} on attempt {attempt + 1}")
                        else:
                            print(f"⚠️ Failed to search contacts on attempt {attempt + 1}: {response.status_code}")
                    
                except Exception as e:
                    print(f"⚠️ Could not update referred person contact type: {str(e)}")
                
                # Create a separate contact for the person making the referral
                if original_first_name and original_last_name:
                    referral_source_full_name = f"{original_first_name} {original_last_name}".strip()
                    referral_source_contact_name = create_contact_via_api(
                        referral_source_full_name, 
                        original_email, 
                        original_phone, 
                        "Referral Source"
                    )
                    if referral_source_contact_name:
                        link_contact_to_lead(referral_source_contact_name, lead_name)
            else:
                # For non-referral inquiries, let ERPNext handle contact creation automatically
                pass
            
            return lead_name
        else:
            print(f"❌ Failed to create Lead: {response.status_code} - {response.text}")
            return None
            
    except Exception as e:
        print(f"❌ Error creating Lead: {str(e)}")
        return None

def log_json_data(json_data, lead_data, status="SUCCESS", error_message=None):
    """Log the JSON data and fields for debugging purposes"""
    try:
        log_entry = {
            'timestamp': datetime.now().isoformat(),
            'type': 'lead_api_input',
            'email': lead_data.get('email', 'unknown'),
            'inquiry_type': lead_data.get('inquiry', 'unknown'),
            'json_string': json_data,
            'parsed_fields': lead_data,
            'status': status
        }
        
        if error_message:
            log_entry['error_message'] = error_message
        
        with open('lead_api_json.log', 'a') as f:
            f.write(json.dumps(log_entry) + '\n')
        
        print(f"✅ Logged JSON data for {lead_data.get('email', 'unknown')} - Status: {status}")
        
    except Exception as e:
        print(f"⚠️ Failed to log JSON data: {str(e)}")

def main():
    """Main function to create Lead from JSON input"""
    if len(sys.argv) != 2:
        print("Usage: python create_client_lead_api.py '<json_data>'")
        print("Example: python create_client_lead_api.py '{\"first_name\": \"John\", \"last_name\": \"Doe\", \"email\": \"john@example.com\", \"phone\": \"555-1234\", \"inquiry\": \"general\", \"source\": \"website\", \"message\": \"Test message\"}'")
        sys.exit(1)
    
    json_data = None
    lead_data = None
    
    try:
        # Parse JSON input first to enable logging
        json_data = sys.argv[1]
        lead_data = json.loads(json_data)
        
        # Load API credentials
        load_api_credentials()
        
        # Test authentication first
        print("🔐 Testing authentication...")
        if not test_authentication():
            error_msg = "Authentication failed. Please check your API credentials and ERPNext URL."
            log_json_data(json_data, lead_data, "FAILED", error_msg)
            print(f"❌ {error_msg}")
            sys.exit(1)
        
        print(f"📥 Processing lead data for: {lead_data.get('email', 'unknown')}")
        
        # Create the lead
        lead_name = create_lead_via_api(lead_data)
        
        if lead_name:
            log_json_data(json_data, lead_data, "SUCCESS")
            print(f"✅ SUCCESS: Created Lead {lead_name}")
            sys.exit(0)
        else:
            error_msg = "Could not create Lead"
            log_json_data(json_data, lead_data, "FAILED", error_msg)
            print(f"❌ FAILED: {error_msg}")
            sys.exit(1)
            
    except json.JSONDecodeError as e:
        error_msg = f"Invalid JSON data: {str(e)}"
        if json_data and lead_data:
            log_json_data(json_data, lead_data, "FAILED", error_msg)
        print(f"❌ {error_msg}")
        sys.exit(1)
    except Exception as e:
        error_msg = f"Unexpected error: {str(e)}"
        if json_data and lead_data:
            log_json_data(json_data, lead_data, "FAILED", error_msg)
        print(f"❌ {error_msg}")
        sys.exit(1)

if __name__ == "__main__":
    main()

