from biobridge.definitions.cells.eukaryotic_cell import EukaryoticCell
from typing import Optional


class MuscleCell(EukaryoticCell):
    def __init__(self, name: str, fiber_type: Optional[str] = "skeletal", contraction_speed: Optional[float] = 1.0,
                 force_output: Optional[float] = 1.0, mitochondria_density: Optional[float] = 1.0,
                 sarcomere_length: Optional[float] = 2.5, fatigue_resistance: Optional[float] = 1.0, contractile_force: Optional[float] = 1.0, **kwargs):
        """
        Initialize a new MuscleCell object, a specialized type of Cell.

        :param name: Name of the muscle cell
        :param fiber_type: Type of muscle fiber (e.g., "skeletal", "cardiac", "smooth")
        :param contraction_speed: Speed of contraction relative to other cells
        :param force_output: Force output of the muscle cell
        :param mitochondria_density: Density of mitochondria in the muscle cell
        :param sarcomere_length: Length of the sarcomere, the contractile unit of muscle cells
        :param fatigue_resistance: Muscle cell's resistance to fatigue
        :param kwargs: Other parameters passed to the base Cell class
        """
        super().__init__(name, **kwargs)  # Call the base class initializer

        # Muscle-specific attributes
        self.fiber_type = fiber_type  # Type of muscle fiber (e.g., skeletal, cardiac, smooth)
        self.contraction_speed = contraction_speed  # Relative speed of contraction
        self.force_output = force_output  # The force output of the muscle cell
        self.mitochondria_density = mitochondria_density  # Density of mitochondria for ATP production
        self.sarcomere_length = sarcomere_length  # Length of sarcomeres (contractile units)
        self.fatigue_resistance = fatigue_resistance  # Muscle cell's resistance to fatigue
        self.contracted = False  # New attribute to track contraction state
        self.contractile_force = contractile_force
        # Adding more mitochondria for energy production, common in muscle cells
        self.add_mitochondrion(efficiency=mitochondria_density, quantity=int(100 * mitochondria_density))

    def contract(self, intensity: float) -> float:
        """
        Simulate the contraction of the muscle cell.

        :param intensity: A value between 0 and 1 representing the contraction intensity
        :return: The force generated by the muscle cell during contraction
        """
        if not 0 <= intensity <= 1:
            raise ValueError("Contraction intensity must be between 0 and 1.")

        # Force output depends on contraction speed, force capability, and intensity
        force = self.force_output * self.contraction_speed * intensity
        print(f"Muscle cell {self.name} contracts with force: {force}")

        # Adjust health slightly depending on contraction intensity
        self.health -= intensity * 0.1 * (1 - self.fatigue_resistance)
        self.health = max(0, self.health)

        self.contracted = True  # Set the contracted state to True
        return force

    def relax(self) -> None:
        """
        Relax the muscle cell, returning it to its resting state.
        """
        if self.contracted:
            self.contracted = False
            print(f"Muscle cell {self.name} relaxes and returns to resting state.")
        else:
            print(f"Muscle cell {self.name} is already in a relaxed state.")

    def fatigue(self) -> None:
        """
        Simulate muscle fatigue, reducing the force output over time.
        """
        if self.fatigue_resistance > 0.5:
            print(f"Muscle cell {self.name} resists fatigue well.")
        else:
            fatigue_effect = 1.0 - self.fatigue_resistance
            self.force_output *= (1.0 - fatigue_effect)
            print(f"Muscle cell {self.name} is fatigued, force output reduced to: {self.force_output:.2f}")

    def regenerate_muscle(self, regeneration_rate: float = 0.1) -> None:
        """
        Simulate the regeneration of the muscle cell, recovering some lost health.

        :param regeneration_rate: Rate at which the cell regenerates health (0 to 1)
        """
        health_recovery = regeneration_rate * (100 - self.health)
        self.health = min(100, self.health + health_recovery)
        print(f"Muscle cell {self.name} regenerates, health now: {self.health:.2f}")

    def describe(self) -> str:
        """
        Provide a detailed description of the muscle cell, extending the base cell description.
        """
        base_description = super().describe()
        muscle_description = [
            f"Fiber Type: {self.fiber_type}",
            f"Contraction Speed: {self.contraction_speed:.2f}",
            f"Force Output: {self.force_output:.2f}",
            f"Mitochondria Density: {self.mitochondria_density:.2f}",
            f"Sarcomere Length: {self.sarcomere_length:.2f} µm",
            f"Fatigue Resistance: {self.fatigue_resistance:.2f}",
            f"Contracted: {'Yes' if self.contracted else 'No'}"
        ]
        return base_description + "\n" + "\n".join(muscle_description)
