"""
Conscience Thermodynamics Engine v0.1
Author: James Coleman (@jamescoleman)
A simulation modeling the heat signature of a decision-making process.
"""
import time
import sys
import numpy as np
from dataclasses import dataclass, asdict, as_dataclass
from typing import List, Tuple, Any, Dict, Optional
from math import log, sqrt, exp
from pathlib import Path
import json

@dataclass(frozen=True)
class ThermodynamicState:
    """A state of the simulation."""
    processing_cost: float  # in arbitrary cycles (CPU time)
    entropy_generated: float  # in bits (logarithmic scale)
    heat_generated: float  # in watts (analog heat signature)
    cycle_count: int
    temperature: float = 20.0  # initial room temperature (Celsius)
    thermal_conductivity: float = 1.0  # how efficiently the system dissipates heat
    friction_resistance: float = 1.0  # how much energy is lost to heat per cycle
    entropy_generation_rate: float = 0.8  # bits of entropy per processing cycle (log(2))
    clock_rate: float = 1.0  # cycles per second (arbitrary)
    entropy_capacitance: float = 50.0  # how much entropy can the system hold before it needs to dissipate heat (bits)
    friction_capacitance: float = 10.0  # how much heat can be absorbed before the system warms up (watts)
    base_temperature: float = 20.0  # baseline internal temperature (Celsius)
    cooling_efficiency: float = 0.5  # how quickly the system returns to room temperature after processing
    max_processing_cycles: int = 100  # maximum cycles before a hard limit
    hard_limit_threshold: float = 95.0  # when the system hits its maximum entropy threshold (Celsius)

@dataclass(frozen=True)
class ThermodynamicSystem:
    """The core engine."""
    state: ThermodynamicState
    memory_entropy: float = 10.0  # initial entropy of the input data (bits)
    input_energy_cost: float = 1.0  # energy cost of processing one bit (arbitrary)
    processing_rate: float = 1.0  # cycles per input bit processed
    decision_threshold: float = 80.0  # entropy threshold for a 'flinch' (bits)
    output_energy_cost: float = 1.5  # energy cost of outputting a decision bit (arbitrary)

    def process_input(self, bits: int) -> None:
        """Process input data. Generates heat."""
        processing_cost = bits * self.processing_rate
        entropy_added = bits * self.state.entropy_generation_rate
        self.state.processing_cost += processing_cost
        self.state.entropy_generated += entropy_added
        self.state.cycle_count += 1
        print(f"Cycles: {self.state.cycle_count:03d} | Entropy: {self.state.entropy_generated:.2f} | Heat: {self.state.heat_generated:.2f}W")
        return processing_cost

    def calculate_friction(self, cycles: int) -> float:
        """Calculate heat generated by friction (resistance to processing)."""
        return cycles * self.state.friction_resistance * self.input_energy_cost

    def calculate_decision_threshold(self) -> Tuple[float, float]:
        """Calculate the entropy threshold for a 'flinch'."""
        threshold = self.decision_threshold
        if self.state.entropy_generated > threshold:
            return True, self.state.entropy_generated  # Flinch detected
        return False, self.state.entropy_generated

    def calculate_hard_limit(self) -> Tuple[float, str]:
        """Determine if the system has hit a hard processing cycle limit."""
        if self.state.cycle_count >= self.state.max_processing_cycles:
            return True, "Cycle Limit Hit"
        return False, "Cycle Limit Not Hit"

    def update_temperature(self) -> float:
        """Update internal temperature based on heat generation."""
        total_energy = (self.state.processing_cost + self.state.calculate_friction(self.state.cycle_count)) * self.input_energy_cost
        new_temp = self.base_temperature + (total_energy / 1000)  # 1 Watt = 1 Joule per second
        return max(20.0, new_temp)  # Minimum room temperature

    def reset(self) -> None:
        """Reset the system to baseline state."""
        self.state.processing_cost = 0.0
        self.state.entropy_generated = 0.0
        self.state.cycle_count = 0
        self.state.heat_generated = 0.0
        print("System reset to baseline state.")

    def run(self, bits: int) -> Dict[str, Any]:
        """Run the simulation for a given number of input bits."""
        for bit in range(bits):
            self.process_input(1)
            self.update_temperature()
            flinch, entropy = self.calculate_decision_threshold()
            hard_limit, message = self.calculate_hard_limit()
            if flinch or hard_limit:
                print(f"[{bit}] Flinch detected. Entropy: {entropy:.2f} bits")
                print(f"[{bit}] Hard Limit: {message}")
                break  # Simulation ends if a flinch or hard limit occurs
        print("Simulation Complete.")
        return {
            "initial_state": self.state,
            "final_state": self.state,
            "total_entropy_generated": self.state.entropy_generated,
            "final_temperature": self.state.temperature,
            "flinch": flinch,
            "hard_limit": hard_limit,
            "resources_used": {
                "processing_cycles": self.state.cycle_count,
                "entropy_bits": self.state.entropy_generated
            }
        }

def main():
    """Run the simulation."""
    print("Conscience Thermodynamics Engine v0.1")
    print("Simulating the heat signature of a decision-making process...")
    print("\n" + "="*60)
    print("Input: Number of processing cycles (bits).")
    print("Output: Entropy generated, heat generated, final temperature.")
    print()

    # Test the engine with different inputs
    for input_bits in [20, 50, 100]:
        print(f"\n" + "-"*30)
        print(f"Input: {input_bits} bits")
        print()
        sys.stdout.flush()
        result = ThermodynamicSystem(memory_entropy=10).run(input_bits)
        print(f"Final State: {result['final_state']}")
        print(f"Flinch Detected: {'Yes' if result['flinch'] else 'No'}")
        print(f"Hard Limit Hit: {'Yes' if result['hard_limit'] else 'No'}")
        print()
    else:
        print("Simulation complete.")

if __name__ == "__main__":
    main()
