"""
Dynamic Polymorphic XOR Key RAM Encryption Engine for FreeExile.
Protects sensitive gameplay state (HP, Mana, Currency, Cooldowns) against
memory scanners and debuggers (Cheat Engine, GameGem, memory freeze hooks).
Implements automatic dynamic key mutation and cryptographic canary integrity verification.
"""

from __future__ import annotations
import math
import struct
import secrets
from typing import TypeVar, Generic, Union, Optional
from dataclasses import dataclass

T = TypeVar("T", int, float)
_CANARY_SALT = 0x5F3759DF499602D2


class MemoryTamperViolationError(Exception):
    """Raised when memory corruption, address freeze, or Cheat Engine tampering is detected."""
    pass


class PolymorphicRAMVariable(Generic[T]):
    """
    Polymorphic memory-protected variable.
    Masks internal value with a 64-bit rotating XOR key that changes dynamically
    upon every access or frame cycle. Verifies cryptographic canary on read.
    """

    def __init__(self, initial_value: T, variable_name: str = "unnamed_stat") -> None:
        self.variable_name = variable_name
        self._is_float = isinstance(initial_value, float)
        self._mask_key: int = 0
        self._masked_val: int = 0
        self._canary_hash: int = 0
        self._access_count: int = 0
        self.set_value(initial_value)

    def _to_raw_int(self, value: T) -> int:
        """Converts float or int to an exact 64-bit integer representation."""
        if self._is_float:
            packed = struct.pack(">d", float(value))
            return struct.unpack(">Q", packed)[0]
        packed = struct.pack(">q", int(value))
        return struct.unpack(">Q", packed)[0]

    def _from_raw_int(self, raw_int: int) -> T:
        """Restores float or int from 64-bit integer representation."""
        if self._is_float:
            packed = struct.pack(">Q", raw_int & 0xFFFFFFFFFFFFFFFF)
            return struct.unpack(">d", packed)[0]  # type: ignore[return-value]
        packed = struct.pack(">Q", raw_int & 0xFFFFFFFFFFFFFFFF)
        return struct.unpack(">q", packed)[0]  # type: ignore[return-value]

    def _compute_canary(self, raw_int: int, key: int) -> int:
        """Computes internal integrity canary to detect external memory tampering."""
        h = ((raw_int ^ _CANARY_SALT) + (key ^ 0xA5A5A5A5A5A5A5A5)) & 0xFFFFFFFFFFFFFFFF
        h ^= (h >> 33)
        h = (h * 0xFF51AFD7ED558CCD) & 0xFFFFFFFFFFFFFFFF
        h ^= (h >> 33)
        return h

    def set_value(self, new_value: T) -> None:
        """Encrypts value with a newly generated random 64-bit polymorphic XOR key."""
        raw_int = self._to_raw_int(new_value)
        self._mask_key = secrets.randbits(64)
        self._masked_val = raw_int ^ self._mask_key
        self._canary_hash = self._compute_canary(raw_int, self._mask_key)
        self._access_count += 1

    def get_value(self) -> T:
        """
        Decrypts value on-the-fly, verifies integrity canary,
        and dynamically rotates the key to scramble RAM address contents.
        """
        raw_int = self._masked_val ^ self._mask_key
        expected_canary = self._compute_canary(raw_int, self._mask_key)
        if expected_canary != self._canary_hash:
            raise MemoryTamperViolationError(
                f"Memory tampering detected on {self.variable_name}! "
                f"Canary mismatch (expected {expected_canary:#x}, got {self._canary_hash:#x}). "
                "Cheat Engine / GameGem memory freeze intercepted."
            )

        val = self._from_raw_int(raw_int)
        # Dynamically rotate mask key on read to continuously defeat memory scanners
        self.set_value(val)
        return val

    def cycle_mask(self) -> None:
        """Cycles encryption mask key without modifying logical value (called per-frame)."""
        self.get_value()

    def verify_integrity(self) -> bool:
        """Non-mutating integrity check against memory corruption."""
        raw_int = self._masked_val ^ self._mask_key
        return self._compute_canary(raw_int, self._mask_key) == self._canary_hash

    def inject_raw_memory_corruption(self, corrupted_masked_val: int) -> None:
        """Simulates external memory hacker / Cheat Engine overwriting memory bytes."""
        self._masked_val = corrupted_masked_val


class ProtectedPlayerStats:
    """
    Secure client/server container for critical gameplay attributes.
    Every stat is individually encapsulated in a PolymorphicRAMVariable.
    """

    def __init__(
        self,
        hp: float = 1000.0,
        max_hp: float = 1000.0,
        mana: float = 500.0,
        max_mana: float = 500.0,
        currency_hon_nguyen: int = 0,
        cooldown_ms: int = 0,
    ) -> None:
        self.hp = PolymorphicRAMVariable[float](hp, "player_current_hp")
        self.max_hp = PolymorphicRAMVariable[float](max_hp, "player_max_hp")
        self.mana = PolymorphicRAMVariable[float](mana, "player_current_mana")
        self.max_mana = PolymorphicRAMVariable[float](max_mana, "player_max_mana")
        self.currency_hon_nguyen = PolymorphicRAMVariable[int](currency_hon_nguyen, "currency_hon_nguyen")
        self.cooldown_ms = PolymorphicRAMVariable[int](cooldown_ms, "skill_cooldown_ms")

    def take_damage(self, amount: float) -> float:
        """Safely applies damage with polymorphic RAM mutation."""
        curr_hp = self.hp.get_value()
        new_hp = max(0.0, curr_hp - max(0.0, amount))
        self.hp.set_value(new_hp)
        return new_hp

    def heal(self, amount: float) -> float:
        """Safely restores HP up to max_hp."""
        curr_hp = self.hp.get_value()
        cap = self.max_hp.get_value()
        new_hp = min(cap, curr_hp + max(0.0, amount))
        self.hp.set_value(new_hp)
        return new_hp

    def spend_mana(self, cost: float) -> bool:
        """Safely deducts mana if sufficient balance exists."""
        curr_mana = self.mana.get_value()
        if curr_mana < cost:
            return False
        self.mana.set_value(curr_mana - cost)
        return True

    def add_currency(self, amount: int) -> int:
        """Adds Primal Currency Hon Nguyen."""
        curr = self.currency_hon_nguyen.get_value()
        new_curr = max(0, curr + amount)
        self.currency_hon_nguyen.set_value(new_curr)
        return new_curr

    def spend_currency(self, amount: int) -> bool:
        """Spends currency if sufficient balance exists."""
        curr = self.currency_hon_nguyen.get_value()
        if curr < amount:
            return False
        self.currency_hon_nguyen.set_value(curr - amount)
        return True

    def cycle_all_masks(self) -> None:
        """Cycles all XOR keys across all stats (called on frame tick)."""
        self.hp.cycle_mask()
        self.max_hp.cycle_mask()
        self.mana.cycle_mask()
        self.max_mana.cycle_mask()
        self.currency_hon_nguyen.cycle_mask()
        self.cooldown_ms.cycle_mask()

    def verify_all_integrity(self) -> bool:
        """Verifies integrity across all protected attributes."""
        return (
            self.hp.verify_integrity()
            and self.max_hp.verify_integrity()
            and self.mana.verify_integrity()
            and self.max_mana.verify_integrity()
            and self.currency_hon_nguyen.verify_integrity()
            and self.cooldown_ms.verify_integrity()
        )
