#!/usr/bin/env python3
"""
Job Applicant Creator for Wright Choice HS
Creates Job Applicant DocTypes directly via ERPNext API
Based on the email_intake_job_worker_v2.py structure
"""

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"
API_KEY = ""
API_SECRET = ""

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")
        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_or_update_contact(full_name, email, phone):
    """Create or update a Contact via ERPNext API"""
    try:
        # Check if contact already exists by 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_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,
            "email_ids": [{"email_id": email.lower().strip(), "is_primary": 1}],
            "custom_contact_type": "Job Applicant"
        }
        
        if phone:
            contact_data["phone_nos"] = [{"phone": phone, "is_primary_mobile_no": 1}]
        
        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: Job Applicant)")
            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 ensure_contact_dynamic_link(contact_name, job_applicant_name):
    """Ensure Contact has dynamic link to Job Applicant"""
    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') == 'Job Applicant' and link.get('link_name') == job_applicant_name:
                print(f"ℹ️ Contact {contact_name} already linked to Job Applicant {job_applicant_name}")
                return
        
        # Add new link
        if 'links' not in contact_doc:
            contact_doc['links'] = []
        contact_doc['links'].append({
            "link_doctype": "Job Applicant",
            "link_name": job_applicant_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 Job Applicant {job_applicant_name}")
        else:
            print(f"❌ Failed to link Contact to Job Applicant: {response.status_code} - {response.text}")
            
    except Exception as e:
        print(f"❌ Error linking Contact to Job Applicant: {str(e)}")

def get_job_opening_info(position):
    """Get Job Opening information by position title"""
    try:
        # First get the list of job openings matching the position
        response = requests.get(
            f"{ERPNEXT_URL}/api/resource/Job Opening",
            params={"filters": json.dumps({"job_title": position})},
            headers=get_auth_headers(),
            verify=False
        )
        
        if response.status_code == 200:
            job_openings = response.json().get('data', [])
            if job_openings:
                job_name = job_openings[0].get('name')
                
                # Get the full job opening record with all fields
                detail_response = requests.get(
                    f"{ERPNEXT_URL}/api/resource/Job Opening/{job_name}",
                    headers=get_auth_headers(),
                    verify=False
                )
                
                if detail_response.status_code == 200:
                    job_detail = detail_response.json().get('data', {})
                    job_title = job_detail.get('job_title')
                    designation = job_detail.get('designation')
                    print(f"✅ Found Job Opening: {job_title} -> {designation}")
                    return job_name, designation
        
        print(f"❌ No Job Opening found for position: {position}")
        return None, None
        
    except Exception as e:
        print(f"❌ Error getting Job Opening info: {str(e)}")
        return None, None

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

def upload_file_to_erpnext(file_path, doctype, docname, first_name="", last_name=""):
    """Upload a file to ERPNext and return the file URL"""
    try:
        if not file_path or not os.path.exists(file_path):
            print(f"❌ File not found: {file_path}")
            return None
        
        # Read the file
        with open(file_path, 'rb') as f:
            file_content = f.read()
        
        # Create filename in format FirstName_LastName_Resume with original extension
        original_filename = os.path.basename(file_path)
        file_extension = os.path.splitext(original_filename)[1]
        
        if first_name and last_name:
            filename = f"{first_name}_{last_name}_Resume{file_extension}"
        else:
            filename = original_filename
        
        # Upload file to ERPNext
        files = {
            'file': (filename, file_content, 'application/pdf'),
            'is_private': (None, '0'),
            'doctype': (None, doctype),
            'docname': (None, docname)
        }
        
        response = requests.post(
            f"{ERPNEXT_URL}/api/method/upload_file",
            files=files,
            headers={
                "Authorization": f"token {API_KEY}:{API_SECRET}",
                "Accept": "application/json"
            },
            verify=False
        )
        
        if response.status_code == 200:
            result = response.json()
            if result.get('message'):
                file_url = result['message'].get('file_url')
                print(f"✅ File uploaded: {file_url}")
                return file_url
            else:
                print(f"❌ File upload failed: {response.text}")
                return None
        else:
            print(f"❌ File upload failed: {response.status_code} - {response.text}")
            return None
            
    except Exception as e:
        print(f"❌ Error uploading file: {str(e)}")
        return None

def create_job_applicant_via_api(applicant_data):
    """Create a Job Applicant via ERPNext API"""
    try:
        # Validate required fields
        if not applicant_data.get('email'):
            print("❌ Email is required")
            return None
            
        full_name = " ".join([applicant_data.get('first_name', ''), applicant_data.get('last_name', '')]).strip()
        if not full_name:
            print("❌ Full name is required")
            return None
        
        email = applicant_data.get('email').lower().strip()
        
        # Check for duplicate
        if check_duplicate_applicant(email):
            print(f"⏭️ Duplicate Job Applicant exists for {email}")
            return None
        
        # Get job opening information
        position = applicant_data.get('job_title', '')
        job_opening_name, designation = get_job_opening_info(position)
        
        # Prepare Job Applicant data
        job_applicant_data = {
            "applicant_name": full_name,
            "email_id": email,
            "phone_number": applicant_data.get('phone_number', ''),
            "source": applicant_data.get('source', 'Website'),
            "custom_why_are_you_a_good_fit": applicant_data.get('custom_why_are_you_a_good_fit', ''),
            "created_on_display": datetime.now().isoformat(),
            "custom_city": applicant_data.get('custom_city', ''),
            "custom_first_name": applicant_data.get('custom_first_name', ''),
            "custom_last_name": applicant_data.get('custom_last_name', '')
        }
        
        # Add county if provided (County DocType doesn't exist, so treat as text field)
        county = applicant_data.get('custom_county_of_interest', '')
        if county:
            job_applicant_data["custom_county_of_interest"] = county
            print(f"✅ County '{county}' added")
        
        if job_opening_name:
            job_applicant_data["job_title"] = job_opening_name
        if designation:
            job_applicant_data["designation"] = designation
        
        # Create the Job Applicant
        response = requests.post(
            f"{ERPNEXT_URL}/api/resource/Job Applicant",
            json=job_applicant_data,
            headers=get_auth_headers(),
            verify=False
        )
        
        if response.status_code in [200, 201]:
            applicant_name = response.json().get('data', {}).get('name')
            print(f"✅ Created Job Applicant: {applicant_name}")
            
            # Upload resume file if provided
            resume_filepath = applicant_data.get('resume_filepath')
            if resume_filepath:
                first_name = applicant_data.get('first_name', applicant_data.get('custom_first_name', ''))
                last_name = applicant_data.get('last_name', applicant_data.get('custom_last_name', ''))
                file_url = upload_file_to_erpnext(resume_filepath, 'Job Applicant', applicant_name, first_name, last_name)
                if file_url:
                    print(f"✅ Resume file attached to Job Applicant {applicant_name}")
            
            # Create and link contact
            contact_name = create_or_update_contact(full_name, email, applicant_data.get('phone_number', ''))
            if contact_name:
                # Update the Job Applicant with contact link
                update_data = {"custom_contact": contact_name}
                update_response = requests.put(
                    f"{ERPNEXT_URL}/api/resource/Job Applicant/{applicant_name}",
                    json=update_data,
                    headers=get_auth_headers(),
                    verify=False
                )
                
                if update_response.status_code == 200:
                    print(f"✅ Updated Job Applicant {applicant_name} with Contact {contact_name}")
                
                # Link contact to job applicant
                ensure_contact_dynamic_link(contact_name, applicant_name)
            
            return applicant_name
        else:
            print(f"❌ Failed to create Job Applicant: {response.status_code} - {response.text}")
            return None
            
    except Exception as e:
        print(f"❌ Error creating Job Applicant: {str(e)}")
        return None

def log_json_data(json_data, applicant_data, status="SUCCESS", error_message=None):
    """Log the JSON data and fields for debugging purposes"""
    try:
        log_entry = {
            'timestamp': datetime.now().isoformat(),
            'type': 'job_applicant_api_input',
            'email': applicant_data.get('email', 'unknown'),
            'json_string': json_data,
            'parsed_fields': applicant_data,
            'status': status
        }
        
        if error_message:
            log_entry['error_message'] = error_message
        
        with open('job_applicant_api_json.log', 'a') as f:
            f.write(json.dumps(log_entry) + '\n')
        
        print(f"✅ Logged JSON data for {applicant_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 Job Applicant from JSON input"""
    if len(sys.argv) != 2:
        print("Usage: python create_job_applicant_api.py '<json_data>'")
        print("Example: python create_job_applicant_api.py '{\"first_name\": \"John\", \"last_name\": \"Doe\", \"email\": \"john@example.com\", \"phone_number\": \"555-1234\", \"job_title\": \"Companion/Sitter\", \"source\": \"website\", \"custom_why_are_you_a_good_fit\": \"I am interested in this position\", \"custom_city\": \"Springfield\", \"custom_county_of_interest\": \"Fairfax\"}'")
        sys.exit(1)
    
    json_data = None
    applicant_data = None
    
    try:
        # Parse JSON input first to enable logging
        json_data = sys.argv[1]
        applicant_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, applicant_data, "FAILED", error_msg)
            print(f"❌ {error_msg}")
            sys.exit(1)
        
        print(f"📥 Processing job applicant data for: {applicant_data.get('email', 'unknown')}")
        
        # Create the job applicant
        applicant_name = create_job_applicant_via_api(applicant_data)
        
        if applicant_name:
            log_json_data(json_data, applicant_data, "SUCCESS")
            print(f"✅ SUCCESS: Created Job Applicant {applicant_name}")
            sys.exit(0)
        else:
            error_msg = "Could not create Job Applicant"
            log_json_data(json_data, applicant_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 applicant_data:
            log_json_data(json_data, applicant_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 applicant_data:
            log_json_data(json_data, applicant_data, "FAILED", error_msg)
        print(f"❌ {error_msg}")
        sys.exit(1)

if __name__ == "__main__":
    main()