"""
Automation management functionality for templates
"""
from typing import List, Optional, Dict, Any
from .base import TemplateManagerBase
from ..models import AutomatedAction, TallyfyError
from email_validator import validate_email, EmailNotValidError


class TemplateAutomation(TemplateManagerBase):
    """Handles automation rules creation, management, and optimization"""

    def create_automation_rule(self, org_id: str, template_id: str, rule_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Create conditional automation (if-then rules).
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            rule_data: Dictionary containing automation rule data
            
        Returns:
            Dictionary containing created automation rule information
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/automated-actions"
            
            # Validate rule data
            if not isinstance(rule_data, dict):
                raise ValueError("Rule data must be a dictionary")
            
            # Build automation data
            automation_data = {}
            
            # Add alias if provided
            if 'alias' in rule_data:
                automation_data['automated_alias'] = str(rule_data['alias'])
            
            # Add conditions
            if 'conditions' in rule_data and rule_data['conditions']:
                automation_data['conditions'] = rule_data['conditions']
            else:
                raise ValueError("Automation rule must have conditions")
            
            # Add actions
            if 'actions' in rule_data and rule_data['actions']:
                automation_data['then_actions'] = rule_data['actions']
            else:
                raise ValueError("Automation rule must have actions")
            
            # Add condition logic (AND/OR)
            if 'condition_logic' in rule_data:
                automation_data['condition_logic'] = rule_data['condition_logic']
            
            response_data = self.sdk._make_request('POST', endpoint, data=automation_data)
            
            if isinstance(response_data, dict):
                if 'data' in response_data:
                    return response_data['data']
                return response_data
            else:
                self.sdk.logger.warning("Unexpected response format for automation rule creation")
                return {'success': True, 'created_rule': automation_data}
                
        except TallyfyError:
            raise
        except ValueError as e:
            raise TallyfyError(f"Invalid automation rule data: {e}")
        except Exception as e:
            self._handle_api_error(e, "create automation rule", org_id=org_id, template_id=template_id)

    def update_automation_rule(self, org_id: str, template_id: str, automation_id: str, update_data: Dict[str, Any]) -> Dict[str, Any]:
        """
        Modify automation conditions and actions.
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            automation_id: Automation rule ID to update
            update_data: Dictionary containing fields to update
            
        Returns:
            Dictionary containing updated automation rule information
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/automated-actions/{automation_id}"
            
            # Validate update data
            if not isinstance(update_data, dict):
                raise ValueError("Update data must be a dictionary")
            
            # Build update payload with allowed fields
            allowed_fields = ['automated_alias', 'conditions', 'then_actions', 'condition_logic']
            validated_data = {}
            
            for field, value in update_data.items():
                if field in allowed_fields:
                    validated_data[field] = value
                elif field == 'alias':  # Map alias to automated_alias
                    validated_data['automated_alias'] = str(value)
                elif field == 'actions':  # Map actions to then_actions
                    validated_data['then_actions'] = value
                else:
                    self.sdk.logger.warning(f"Ignoring unknown automation field: {field}")
            
            if not validated_data:
                raise ValueError("No valid automation fields provided for update")

            # Fetch current automation rule — API requires full conditions + then_actions in PUT
            tmpl_resp = self.sdk._make_request(
                'GET',
                f"organizations/{org_id}/checklists/{template_id}",
                params={'with': 'automated_actions'},
            )
            tmpl_data = tmpl_resp.get('data', {}) if isinstance(tmpl_resp, dict) else {}
            automations = tmpl_data.get('automated_actions', [])
            current_rule = next(
                (a for a in automations if str(a.get('id')) == str(automation_id)),
                {},
            )

            # Merge current rule with update data (update_data takes precedence)
            merged = {**current_rule, **validated_data}

            response_data = self.sdk._make_request('PUT', endpoint, data=merged)
            
            if isinstance(response_data, dict):
                if 'data' in response_data:
                    return response_data['data']
                return response_data
            else:
                self.sdk.logger.warning("Unexpected response format for automation rule update")
                return {'success': True, 'updated_rule': validated_data}
                
        except TallyfyError:
            raise
        except ValueError as e:
            raise TallyfyError(f"Invalid update data: {e}")
        except Exception as e:
            self._handle_api_error(e, "update automation rule", org_id=org_id, template_id=template_id, automation_id=automation_id)

    def delete_automation_rule(self, org_id: str, template_id: str, automation_id: str) -> Dict[str, Any]:
        """
        Remove automation rule.
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            automation_id: Automation rule ID to delete
            
        Returns:
            Dictionary containing deletion confirmation
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/automated-actions/{automation_id}"
            
            response_data = self.sdk._make_request('DELETE', endpoint)
            
            if isinstance(response_data, dict):
                return response_data
            else:
                return {'success': True, 'deleted_automation_id': automation_id}
                
        except TallyfyError:
            raise
        except Exception as e:
            self._handle_api_error(e, "delete automation rule", org_id=org_id, template_id=template_id, automation_id=automation_id)

    def add_assignees_to_step(self, org_id: str, template_id: str, step_id: str, assignees: List[int], guests: Optional[List[str]] = None) -> Dict[str, Any]:
        """
        Add assignees to steps (automation-related).
        
        Args:
            org_id: Organization ID
            template_id: Template ID
            step_id: Step ID to add assignees to
            assignees: List of user IDs to assign
            guests: Optional list of guest email addresses
            
        Returns:
            Dictionary containing updated step information
            
        Raises:
            TallyfyError: If the request fails
        """
        self._validate_org_id(org_id)
        self._validate_template_id(template_id)
        
        try:
            endpoint = f"organizations/{org_id}/checklists/{template_id}/steps/{step_id}"
            
            # Validate assignees
            if not isinstance(assignees, list):
                raise ValueError("Assignees must be a list of user IDs")
            
            for user_id in assignees:
                if not isinstance(user_id, int):
                    raise ValueError(f"User ID {user_id} must be an integer")
            
            # Validate guest emails if provided
            validated_guests = []
            if guests:
                if not isinstance(guests, list):
                    raise ValueError("Guests must be a list of email addresses")

                for guest_email in guests:
                    if not isinstance(guest_email, str):
                        raise ValueError(f"Guest email {guest_email} must be a string")
                    try:
                        validation = validate_email(guest_email)
                        # The validated email address
                        email = validation.normalized
                    except EmailNotValidError as e:
                        raise ValueError(f"Invalid email address: {str(e)}")
                    validated_guests.append(email)
            
            # Fetch current step to get the required title field
            get_response = self.sdk._make_request('GET', endpoint)
            current_data = get_response.get('data', get_response) if isinstance(get_response, dict) else {}
            current_title = current_data.get('title', '')
            if not current_title:
                raise TallyfyError("Could not retrieve current step title required for update")

            # Build minimal payload — API rejects full step blob
            current_assignees = current_data.get('assignees', [])
            current_guests = current_data.get('guests', [])
            merged_assignees = list(set(current_assignees + assignees))
            merged_guests = list(set(current_guests + validated_guests))

            update_data = {
                'title': current_title,
                'assignees': merged_assignees,
                'guests': merged_guests,
            }

            response_data = self.sdk._make_request('PUT', endpoint, data=update_data)
            
            if isinstance(response_data, dict):
                if 'data' in response_data:
                    return response_data['data']
                return response_data
            else:
                self.sdk.logger.warning("Unexpected response format for assignee update")
                return {
                    'success': True, 
                    'step_id': step_id,
                    'added_assignees': assignees,
                    'added_guests': validated_guests
                }
                
        except TallyfyError:
            raise
        except ValueError as e:
            raise TallyfyError(f"Invalid assignee data: {e}")
        except Exception as e:
            self._handle_api_error(e, "add assignees to step", org_id=org_id, template_id=template_id, step_id=step_id)

