"""
Automated Penetration & Security Fuzzing Test Suite for FreeExile.
Executes automated attack vectors:
1. Speedhack & Teleport Position Injection
2. Duplicate Transaction & Double-Spending Attacks
3. Packet Replay Attack Injection
4. Ciphertext Bit-Flipping & Tampering Attacks
5. Emulator Linear Touch Vector Bot Attacks
6. Cracked IPA Bundle Attestation Forgery
"""

import unittest
import sys
import os

# Add server directory to path
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "../../server")))

from world.movement_authority import MovementAuthorityEngine, PlayerCharacter
from trade.two_phase_commit import InstantBuyoutEngine, StashItem
from security.packet_cipher import PacketCipherEngine, AntiReplayWindow
from security.touch_biometrics import TouchBiometricsValidator, TouchPoint
from security.app_attest import AppleAppAttestValidator, AttestationToken


class TestPenetrationSuite(unittest.TestCase):
    def test_penetration_speedhack_injection_blocked(self):
        """Attacker injects forged high-velocity coordinates -> Server must rubberband."""
        engine = MovementAuthorityEngine(max_base_speed=6.0)
        p = PlayerCharacter(entity_id=999, x=10.0, y=10.0, move_speed=6.0)
        engine.register_player(p)

        # Attacker tries to leap 200 meters in 1 tick (0.033s)
        valid, rx, ry = engine.validate_and_reconcile_position(
            entity_id=999,
            claimed_x=210.0,
            claimed_y=10.0,
            dt=0.033
        )
        self.assertFalse(valid)
        self.assertEqual(rx, 10.0) # Rubberbanded back to original pos
        self.assertGreater(p.suspicion_score, 0)

    def test_penetration_double_spend_duplication_blocked(self):
        """Attacker fires 2 concurrent buyout requests for the same item -> 2PC must block duplicate."""
        engine = InstantBuyoutEngine()
        seller = engine.register_account("seller_vic")
        buyer1 = engine.register_account("buyer_1")
        buyer2 = engine.register_account("buyer_2")

        buyer1.currencies["HonNguyen"] = 100
        buyer2.currencies["HonNguyen"] = 100

        item = StashItem(
            item_uuid="rare_dagger_unique",
            owner_account_id="seller_vic",
            item_name="Ám Ảnh Đoản Đao",
            asking_price_currency="HonNguyen",
            asking_price_amount=50
        )
        seller.items["rare_dagger_unique"] = item

        # Buyer 1 buys successfully
        ok1, _, _ = engine.execute_instant_buyout("buyer_1", "seller_vic", "rare_dagger_unique", "HonNguyen", 50)
        self.assertTrue(ok1)

        # Buyer 2 attempts simultaneous replay buyout
        ok2, msg, _ = engine.execute_instant_buyout("buyer_2", "seller_vic", "rare_dagger_unique", "HonNguyen", 50)
        self.assertFalse(ok2)
        # Verify item exists in exactly 1 stash (no duplication)
        self.assertIn("rare_dagger_unique", buyer1.items)
        self.assertNotIn("rare_dagger_unique", buyer2.items)
        self.assertNotIn("rare_dagger_unique", seller.items)

    def test_penetration_packet_replay_blocked(self):
        """Attacker intercepts valid packet and replays it -> Anti-Replay window drops it."""
        window = AntiReplayWindow(window_size=64)
        # Legitimate packet 42
        self.assertTrue(window.check_and_update(42))
        # Replayed packet 42
        self.assertFalse(window.check_and_update(42))

    def test_penetration_ciphertext_bitflip_tampering_blocked(self):
        """Attacker flips 1 bit in transit -> Cipher engine detects corrupted HMAC and aborts."""
        engine = PacketCipherEngine(shared_key=b"SHARED_SECRET_KEY_FOR_TESTING_12")
        cipher, tag, nonce = engine.encrypt(b"DROP_DIVINE_LOOT_NOW", seq_num=10)
        
        # Tamper 1 byte
        corrupted = bytes([cipher[0] ^ 0x01]) + cipher[1:]
        with self.assertRaises(ValueError):
            engine.decrypt(corrupted, tag, nonce, seq_num=10)

    def test_penetration_bot_linear_touch_rejected(self):
        """Attacker uses PC emulator / mouse bot with straight line coordinates -> AI detects bot."""
        validator = TouchBiometricsValidator()
        straight_points = [
            TouchPoint(x=float(i * 10), y=float(i * 10), timestamp_ms=float(i * 20), major_radius=15.0 + (i % 3), force=1.0)
            for i in range(8)
        ]
        is_human, score, reason = validator.evaluate_touch_sample(straight_points)
        self.assertFalse(is_human)
        self.assertTrue("straight line" in reason.lower() or "bot" in reason.lower() or "detected" in reason.lower())

    def test_penetration_cracked_bundle_id_attestation_rejected(self):
        """Attacker installs cracked IPA with repackaged bundle ID -> Apple App Attest rejects it."""
        validator = AppleAppAttestValidator(expected_bundle_id="com.freeexile.game.ios")
        forged_token = validator.generate_mock_attestation(
            device_id="jailbreak_device",
            bundle_id="com.hack.freeexile.mod"
        )
        is_valid, _ = validator.verify_attestation(forged_token)
        self.assertFalse(is_valid)


if __name__ == "__main__":
    unittest.main()
