"""
Energy Storage Module - Battery and capacitor management
"""

import numpy as np
from typing import List, Dict, Optional, Tuple
from dataclasses import dataclass
from enum import Enum


class StorageType(Enum):
    """Types of energy storage"""
    LITHIUM_ION = "lithium_ion"
    SUPERCAPACITOR = "supercapacitor"
    HYBRID = "hybrid"


@dataclass
class StorageState:
    """Current state of energy storage"""
    state_of_charge: float  # percentage
    voltage: float  # V
    current: float  # A
    temperature: float  # °C
    capacity_remaining: float  # Wh
    cycles_remaining: int


class EnergyStorage:
    """
    Energy storage management for hadal vehicles
    
    Manages batteries and capacitors for reliable power supply
    Supports hybrid systems with supercapacitors for burst power
    """
    
    def __init__(self,
                 battery_capacity: float = 180,  # Wh
                 capacitor_capacity: float = 0.1,  # F
                 nominal_voltage: float = 24,  # V
                 storage_type: StorageType = StorageType.HYBRID):
        """
        Initialize energy storage system
        
        Args:
            battery_capacity: Battery capacity in Wh
            capacitor_capacity: Capacitor capacity in F
            nominal_voltage: System nominal voltage
            storage_type: Type of storage system
        """
        self.battery_capacity = battery_capacity
        self.capacitor_capacity = capacitor_capacity  # ✅ تصحيح المتغير
        self.nominal_voltage = nominal_voltage
        self.storage_type = storage_type
        
        # Battery parameters
        self.battery_chemistry = "Li-ion"
        self.battery_cycles = 500  # Cycle life
        self.battery_efficiency = 0.95
        self.battery_self_discharge = 0.02  # per month
        
        # Capacitor parameters
        self.capacitor_voltage = 2.7  # V per cell
        self.capacitor_esr = 0.1  # Ohms
        self.capacitor_leakage = 1e-6  # A
        
        # Current state
        self.battery_soc = 100.0  # percentage
        self.capacitor_charge = 0.0  # Joules
        self.temperature = 20.0  # °C
        
        # History
        self.soc_history = []
        self.power_history = []
        self.cycle_count = 0
    
    def state_of_charge(self) -> float:
        """Get current state of charge"""
        return self.battery_soc
    
    def manage_power(self,
                    harvested_power: float,  # W
                    load_power: float) -> Tuple[float, float]:  # W
        """
        Manage power flow between harvesting, storage, and load
        
        Args:
            harvested_power: Power from harvesting (W)
            load_power: Power required by load (W)
            
        Returns:
            (power_to_load, power_to_storage)
        """
        # Calculate power balance
        power_balance = harvested_power - load_power
        
        if power_balance >= 0:
            # Excess power - charge storage
            if self.storage_type in [StorageType.LITHIUM_ION, StorageType.HYBRID]:
                # Charge battery
                charge_power = power_balance * self.battery_efficiency
                energy_added = charge_power * 1 / 3600  # Wh per second
                
                self.battery_soc = min(100, self.battery_soc + 
                                       energy_added / self.battery_capacity * 100)
                
                power_to_storage = charge_power
            else:
                power_to_storage = 0
            
            power_to_load = load_power
            
        else:
            # Deficit - draw from storage
            deficit = -power_balance
            
            if self.storage_type == StorageType.HYBRID:
                # Try to use capacitor for short-term deficits
                if self.capacitor_charge > 0:
                    # Use capacitor first
                    cap_power = min(deficit, self.capacitor_charge)
                    deficit -= cap_power
                    self.capacitor_charge -= cap_power
            
            if deficit > 0:
                # Draw from battery
                energy_used = deficit * 1 / 3600  # Wh per second
                self.battery_soc = max(0, self.battery_soc - 
                                      energy_used / self.battery_capacity * 100)
            
            power_to_load = load_power
            power_to_storage = 0
        
        # Record history
        self.soc_history.append(self.battery_soc)
        self.power_history.append({
            'harvested': harvested_power,
            'load': load_power,
            'balance': power_balance
        })
        
        return power_to_load, power_to_storage
    
    def buffer_fluctuations(self,
                          input_power: List[float],
                          time_constant: float = 60) -> List[float]:
        """
        Smooth power fluctuations using capacitor buffer
        
        Args:
            input_power: Raw power measurements (W)
            time_constant: Smoothing time constant (seconds)
            
        Returns:
            Smoothed power output
        """
        if not input_power:
            return []
        
        # Simple low-pass filter
        alpha = 1 / (time_constant + 1)
        smoothed = [input_power[0]]
        
        for p in input_power[1:]:
            smoothed.append(alpha * p + (1 - alpha) * smoothed[-1])
        
        return smoothed
    
    def estimate_endurance(self,
                          avg_power_consumption: float,
                          reserve_percent: float = 20) -> float:
        """
        Estimate remaining mission endurance
        
        Args:
            avg_power_consumption: Average power consumption (W)
            reserve_percent: Reserve capacity to keep (%)
            
        Returns:
            Estimated endurance in hours
        """
        usable_capacity = self.battery_capacity * (1 - reserve_percent / 100)
        usable_energy = usable_capacity * (self.battery_soc / 100)
        
        endurance = usable_energy / avg_power_consumption
        
        return float(endurance)
    
    def charge_capacitor(self, energy: float):
        """Charge supercapacitor"""
        max_energy = 0.5 * self.capacitor_capacity * self.capacitor_voltage**2
        self.capacitor_charge = min(max_energy, self.capacitor_charge + energy)
    
    def discharge_capacitor(self, energy: float) -> float:
        """Discharge supercapacitor"""
        available = min(energy, self.capacitor_charge)
        self.capacitor_charge -= available
        return available
    
    def get_burst_power(self, duration: float) -> float:
        """
        Get available burst power from capacitor
        
        Args:
            duration: Burst duration in seconds
            
        Returns:
            Available burst power in W
        """
        if self.capacitor_charge <= 0:
            return 0
        
        max_burst_power = self.capacitor_charge / duration
        return float(max_burst_power)
    
    def simulate_mission(self,
                        duration_hours: float,
                        avg_load: float,
                        harvesting_profile: Optional[List[float]] = None) -> Dict:
        """
        Simulate energy usage over mission
        
        Args:
            duration_hours: Mission duration
            avg_load: Average load power (W)
            harvesting_profile: Time series of harvested power
            
        Returns:
            Mission energy statistics
        """
        num_steps = int(duration_hours * 3600)
        
        if harvesting_profile is None:
            # Assume constant harvesting at 2.8 mW
            harvesting_profile = [0.0028] * num_steps
        
        soc = []
        energy_used = 0
        energy_harvested = 0
        
        for t in range(min(num_steps, len(harvesting_profile))):
            # Manage power
            _, _ = self.manage_power(
                harvested_power=harvesting_profile[t],
                load_power=avg_load
            )
            
            soc.append(self.battery_soc)
            
            if t > 0:
                energy_used += avg_load / 3600  # Wh per second
                energy_harvested += harvesting_profile[t] / 3600
        
        return {
            'final_soc': self.battery_soc,
            'min_soc': min(soc),
            'energy_used_wh': energy_used,
            'energy_harvested_wh': energy_harvested,
            'net_energy_wh': energy_harvested - energy_used,
            'mission_feasible': self.battery_soc > 10
        }
    
    def get_statistics(self) -> Dict:
        """Get storage statistics"""
        capacitor_energy = 0.5 * self.capacitor_capacity * self.capacitor_voltage**2
        
        return {
            'battery_soc': self.battery_soc,
            'battery_energy_wh': self.battery_capacity * self.battery_soc / 100,
            'capacitor_energy_j': self.capacitor_charge,
            'capacitor_max_j': capacitor_energy,
            'total_energy_wh': (self.battery_capacity * self.battery_soc / 100 +
                               self.capacitor_charge / 3600),
            'cycle_count': self.cycle_count,
            'temperature_c': self.temperature,
            'storage_type': self.storage_type.value
        }
    
    def __repr__(self) -> str:
        stats = self.get_statistics()
        return (f"EnergyStorage(type={self.storage_type.value}, "
                f"SoC={stats['battery_soc']:.1f}%, "
                f"energy={stats['total_energy_wh']:.1f}Wh)")
