"""Services for the school simulation.

Services contain all behavior logic and act on agents (which are data containers).
Only services should schedule events and orchestrate agent interactions.
"""

import sys
from pathlib import Path
from random import random, choice
from typing import List, TYPE_CHECKING

# Add framework src to path for imports
framework_src_path = Path(__file__).parent.parent.parent.parent / "src"
sys.path.insert(0, str(framework_src_path))

from layer1_core.managers.service import Service

if TYPE_CHECKING:
    from demos.school_demo.src.individual import Student, Teacher, Counselor
    from demos.school_demo.src.schoolSchedule import SchoolSchedule

class SubstanceService(Service):
    """Service for handling substance use behaviors."""

    def __init__(self, service_id: str = "substance_service", param_dict: dict = None):
        super().__init__(service_id)
        self.param_dict = param_dict or {}


class DisciplineService(Service):
    """Service for handling all discipline-related behavior in the school."""

    def __init__(self, service_id: str = "discipline_service", param_dict: dict = None):
        super().__init__(service_id)
        self.param_dict = param_dict or {}

    def evaluate_misbehavior(self, student: 'Student', teachers: List['Teacher']) -> None:
        """Evaluate if a student misbehaves and handle the consequences.

        Args:
            student: The student to evaluate
            teachers: List of available teachers
        """
        # Pick a random teacher
        teacher = choice(teachers)

        # Calculate probability of misbehavior based on student mood and teacher attitude
        prob_misbehave = 1 - (student.mood * teacher.attitude)

        if random() < prob_misbehave:
            self.record_misbehavior(student, teacher)

    def record_misbehavior(self, student: 'Student', teacher: 'Teacher') -> None:
        """Record a disciplinary incident for a student.

        Args:
            student: The student who misbehaved
            teacher: The teacher who witnessed the misbehavior
        """
        # Random severity between 0 and 1
        severity: float = random()

        # Apply racial bias
        bias_element = teacher.bias

        if student.race == "NHwhite":
            bias_element = bias_element / 2
        elif student.race == "NHBlack":
            bias_element = bias_element * 2
        elif student.race == "Hispanic":
            bias_element = bias_element * 1.5
        elif student.race == "NAAHPI":
            bias_element = bias_element * 1.5

        # Calculate teacher's response
        teacher_response: float = teacher.attitude * bias_element * severity

        # Record the incident
        student.disciplinaryRecord.append(teacher_response)

        # Affect student mood negatively
        student.mood = student.mood - (0.1 * teacher_response)

    def schedule_behavior_evaluations(self, schedule: 'SchoolSchedule',
                                      students: List['Student'],
                                      teachers: List['Teacher'],
                                      start_step: int, end_step: int) -> None:
        """Schedule random behavior evaluations throughout the simulation.

        Args:
            schedule: The simulation schedule
            students: List of students
            teachers: List of teachers
            start_step: First step to schedule events
            end_step: Last step to schedule events
        """
        for step in range(start_step, end_step):
            # Pick a random student for each step
            student = choice(students)

            # Schedule the evaluation
            schedule.add_event(
                step=step,
                event=lambda s=student, t=teachers: self.evaluate_misbehavior(s, t)
            )


class CounselingService(Service):
    """Service for handling counseling interactions."""

    def __init__(self, service_id: str = "counseling_service", param_dict: dict = None):
        super().__init__(service_id)
        self.param_dict = param_dict or {}

    def provide_counseling(self, student: 'Student', counselor: 'Counselor') -> None:
        """Provide counseling to a student to improve their mood.

        Args:
            student: The student receiving counseling
            counselor: The counselor providing the session
        """
        success: float = random() * counselor.attitude
        self.adjust_mood(student, success)

    def adjust_mood(self, student: 'Student', amount: float) -> None:
        """Adjust a student's mood by a given amount.

        Args:
            student: The student whose mood to adjust
            amount: Amount to adjust mood (can be positive or negative)
        """
        student.mood = student.mood + (amount * 0.1)


class NeighborhoodService(Service):
    """Service for handling neighborhood interactions."""

    def __init__(self, service_id: str = "neighborhood_service", param_dict: dict = None):
        super().__init__(service_id)
        self.param_dict = param_dict or {}


class HousingService(Service):
    """Service for handling housing-related events and disruptions."""

    def __init__(self, service_id: str = "housing_service", param_dict: dict = None):
        super().__init__(service_id)
        self.param_dict = param_dict or {}

    def evaluate_housing_disruption(self, student: 'Student') -> None:
        """Evaluate if a student experiences housing disruption.

        Args:
            student: The student to evaluate
        """
        # Base probability (can be affected by neighborhood factors)
        prob_housing_interruption: float = 0.0

        # If student has a neighborhood, factor in neighborhood characteristics
        if student.neighborhood:
            # Higher eviction rate and lower housing security increase probability
            prob_housing_interruption = (
                student.neighborhood.eviction_rate * 0.5 +
                (1 - student.neighborhood.housing_security) * 0.3
            )

        if random() < prob_housing_interruption:
            self.apply_housing_disruption(student)

    def apply_housing_disruption(self, student: 'Student') -> None:
        """Apply the effects of housing disruption to a student.

        Args:
            student: The student experiencing disruption
        """
        # Significantly negative impact on mood
        student.mood = max(0, student.mood - 0.25)

        # Chance of changing neighborhoods
        prob_change_neighborhood: float = self.param_dict.get('prob_change_neighborhood', 0.5)
        if random() < prob_change_neighborhood and student.neighborhood:
            # Remove from current neighborhood
            student.neighborhood.remove_agent(student)
            # Note: Would need to assign to new neighborhood in a full implementation
            student.neighborhood = None
