"""
Custom Script Automation

Allows customers to write their own automation logic using a safe,
sandboxed Python environment with access to their business data.
"""

from typing import Any, Dict
from django.utils import timezone
import logging

from .registry import BaseAutomation, register_automation, AutomationExecutionError
from smoothschedule.scheduling.schedule.safe_scripting import SafeScriptEngine, SafeScriptAPI, ScriptExecutionError

logger = logging.getLogger(__name__)


@register_automation
class CustomScriptAutomation(BaseAutomation):
    """
    Execute custom customer-written scripts safely.

    Customers can write Python code with if/else, loops, and variables
    while being protected from resource abuse and security issues.
    """

    name = "custom_script"
    display_name = "Custom Script"
    description = "Run your own custom automation logic with safe Python code"
    category = "custom"

    config_schema = {
        'script': {
            'type': 'text',
            'required': True,
            'description': 'Python code to execute (with access to api object)',
        },
        'description': {
            'type': 'text',
            'required': False,
            'description': 'What this script does (for documentation)',
        },
        'initial_variables': {
            'type': 'dict',
            'required': False,
            'description': 'Optional variables to make available to the script',
        },
    }

    def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
        """Execute the customer's script safely"""

        script = self.config.get('script')
        if not script:
            raise AutomationExecutionError("No script provided")

        # Create safe API for customer
        api = SafeScriptAPI(
            business=context.get('business'),
            user=context.get('user'),
            execution_context=context
        )

        # Create script engine
        engine = SafeScriptEngine()

        # Get initial variables
        initial_vars = self.config.get('initial_variables', {})

        # Execute script
        try:
            result = engine.execute(
                script=script,
                api=api,
                initial_vars=initial_vars
            )

            if result['success']:
                return {
                    'success': True,
                    'message': 'Script executed successfully',
                    'data': {
                        'output': result['output'],
                        'result': result['result'],
                        'iterations': result['iterations'],
                        'execution_time': result['execution_time'],
                    }
                }
            else:
                # Script failed but didn't crash
                return {
                    'success': False,
                    'message': f"Script error: {result['error']}",
                    'data': {
                        'output': result['output'],
                        'error': result['error'],
                    }
                }

        except Exception as e:
            logger.error(f"Script execution failed: {e}", exc_info=True)
            raise AutomationExecutionError(f"Script execution failed: {e}")


@register_automation
class ScriptTemplateAutomation(BaseAutomation):
    """
    Pre-built script templates that customers can customize.

    This provides safe, tested scripts with configurable parameters.
    """

    name = "script_template"
    display_name = "Script Template"
    description = "Use a pre-built script template with custom parameters"
    category = "custom"

    # Available templates
    TEMPLATES = {
        'conditional_email': {
            'name': 'Conditional Email Campaign',
            'description': 'Send emails based on custom conditions',
            'parameters': ['condition_field', 'condition_value', 'email_subject', 'email_body'],
            'script': """
# Get customers
customers = api.get_customers(has_email=True, limit=100)

# Filter by condition
matching_customers = []
for customer in customers:
    if customer.get('{condition_field}') == '{condition_value}':
        matching_customers.append(customer)

# Send emails
sent_count = 0
for customer in matching_customers:
    success = api.send_email(
        to=customer['email'],
        subject='{email_subject}',
        body='{email_body}'.format(name=customer['name'])
    )
    if success:
        sent_count += 1

api.log(f"Sent {sent_count} emails to {len(matching_customers)} customers")
result = {{'sent': sent_count, 'matched': len(matching_customers)}}
"""
        },

        'appointment_summary': {
            'name': 'Appointment Summary with Conditions',
            'description': 'Generate custom appointment reports',
            'parameters': ['days_back', 'status_filter', 'email_to'],
            'script': """
# Get appointments from last N days
from datetime import datetime, timedelta

end_date = datetime.now().strftime('%Y-%m-%d')
start_date = (datetime.now() - timedelta(days={days_back})).strftime('%Y-%m-%d')

appointments = api.get_appointments(
    start_date=start_date,
    end_date=end_date,
    status='{status_filter}',
    limit=500
)

# Group by status
status_counts = {{}}
for apt in appointments:
    status = apt['status']
    status_counts[status] = status_counts.get(status, 0) + 1

# Generate report
report = f"Appointment Summary (Last {days_back} days)\\n\\n"
for status, count in status_counts.items():
    report += f"{status}: {count}\\n"
report += f"\\nTotal: {len(appointments)}"

# Send report
api.send_email(
    to='{email_to}',
    subject=f'Appointment Summary - Last {days_back} Days',
    body=report
)

result = {{'total': len(appointments), 'status_counts': status_counts}}
"""
        },

        'follow_up_sequence': {
            'name': 'Smart Follow-up Sequence',
            'description': 'Send different messages based on customer behavior',
            'parameters': ['days_since_visit', 'first_time_message', 'returning_message'],
            'script': """
# Get appointments to find visit history
appointments = api.get_appointments(limit=1000)

# Track customer visit counts
customer_visits = {{}}
for apt in appointments:
    # This is simplified - in real usage you'd track customer IDs
    customer_visits['placeholder'] = customer_visits.get('placeholder', 0) + 1

# Get customers
customers = api.get_customers(has_email=True, limit=100)

# Send personalized follow-ups
for customer in customers:
    visit_count = customer_visits.get(customer['id'], 0)

    if visit_count == 1:
        # First-time customer
        message = '{first_time_message}'.format(name=customer['name'])
        api.send_email(
            to=customer['email'],
            subject='Thanks for Your First Visit!',
            body=message
        )
    elif visit_count > 1:
        # Returning customer
        message = '{returning_message}'.format(name=customer['name'])
        api.send_email(
            to=customer['email'],
            subject='Great to See You Again!',
            body=message
        )

result = {{'customers_processed': len(customers)}}
"""
        },

        'data_export': {
            'name': 'Custom Data Export',
            'description': 'Export filtered data with custom formatting',
            'parameters': ['date_range_days', 'export_email'],
            'script': """
from datetime import datetime, timedelta

# Get date range
end_date = datetime.now().strftime('%Y-%m-%d')
start_date = (datetime.now() - timedelta(days={date_range_days})).strftime('%Y-%m-%d')

# Get data
appointments = api.get_appointments(
    start_date=start_date,
    end_date=end_date,
    limit=500
)

# Format as CSV
csv_data = "Title,Start Time,End Time,Status\\n"
for apt in appointments:
    csv_data += f"{apt['title']},{apt['start_time']},{apt['end_time']},{apt['status']}\\n"

# Send export
api.send_email(
    to='{export_email}',
    subject=f'Data Export - {start_date} to {end_date}',
    body=f"Exported {len(appointments)} appointments:\\n\\n{csv_data}"
)

result = {{'exported_count': len(appointments)}}
"""
        },
    }

    config_schema = {
        'template': {
            'type': 'choice',
            'choices': list(TEMPLATES.keys()),
            'required': True,
            'description': 'Which template to use',
        },
        'parameters': {
            'type': 'dict',
            'required': True,
            'description': 'Template parameters (see template documentation)',
        },
    }

    def execute(self, context: Dict[str, Any]) -> Dict[str, Any]:
        """Execute a script template with customer parameters"""

        template_name = self.config.get('template')
        if template_name not in self.TEMPLATES:
            raise AutomationExecutionError(f"Unknown template: {template_name}")

        template = self.TEMPLATES[template_name]
        parameters = self.config.get('parameters', {})

        # Validate required parameters
        for param in template['parameters']:
            if param not in parameters:
                raise AutomationExecutionError(
                    f"Missing required parameter '{param}' for template '{template_name}'"
                )

        # Fill in template
        try:
            script = template['script'].format(**parameters)
        except KeyError as e:
            raise AutomationExecutionError(f"Template parameter error: {e}")

        # Create safe API
        api = SafeScriptAPI(
            business=context.get('business'),
            user=context.get('user'),
            execution_context=context
        )

        # Execute
        engine = SafeScriptEngine()

        try:
            result = engine.execute(script, api)

            if result['success']:
                return {
                    'success': True,
                    'message': f"Template '{template['name']}' executed successfully",
                    'data': {
                        'output': result['output'],
                        'result': result['result'],
                        'template': template_name,
                    }
                }
            else:
                return {
                    'success': False,
                    'message': f"Template error: {result['error']}",
                    'data': {
                        'output': result['output'],
                        'error': result['error'],
                    }
                }

        except Exception as e:
            logger.error(f"Template execution failed: {e}", exc_info=True)
            raise AutomationExecutionError(f"Template execution failed: {e}")
