"""
Unit tests for Touch Biometrics Anti-Bot Detection in FreeExile.
Verifies rejection of synthetic emulators/bots and acceptance of authentic human touch kinematics.
"""

import unittest
import math
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 security.touch_biometrics import TouchBiometricsValidator, TouchPoint


class TestTouchBiometrics(unittest.TestCase):
    def setUp(self):
        self.validator = TouchBiometricsValidator()

    def test_reject_emulator_zero_radius(self):
        """Emulators or PC mouse injections send zero or 1px touch radius."""
        points = [
            TouchPoint(x=100.0, y=100.0, timestamp_ms=0, major_radius=0.0, force=1.0),
            TouchPoint(x=110.0, y=105.0, timestamp_ms=50, major_radius=0.0, force=1.0),
            TouchPoint(x=120.0, y=110.0, timestamp_ms=100, major_radius=0.0, force=1.0),
        ]
        is_human, score, reason = self.validator.evaluate_touch_sample(points)
        self.assertFalse(is_human)
        self.assertIn("radius too small", reason.lower())
        self.assertLess(score, 0.2)

    def test_reject_bot_perfect_straight_line(self):
        """Bots move along an exact mathematical straight vector without human hand curve."""
        points = []
        for i in range(10):
            # Perfect straight line y = 2x
            points.append(
                TouchPoint(
                    x=float(i * 10),
                    y=float(i * 20),
                    timestamp_ms=float(i * 50 + (i % 2)),
                    major_radius=18.0 + (i % 3),
                    force=1.0
                )
            )
        is_human, score, reason = self.validator.evaluate_touch_sample(points)
        self.assertFalse(is_human)
        self.assertIn("straight line", reason.lower())

    def test_accept_authentic_human_finger_touch(self):
        """Real human finger on iPhone with natural curve, radius deformation, and micro-tremor."""
        points = []
        for i in range(10):
            # Curved trajectory with subtle organic jitter (sinusoidal deviation)
            natural_jitter = math.sin(i * 0.8) * 2.5
            points.append(
                TouchPoint(
                    x=float(i * 10 + natural_jitter),
                    y=float(i * 15 + math.cos(i * 0.6) * 3.0),
                    timestamp_ms=float(i * 45 + (math.sin(i) * 4.0)), # Human temporal variance
                    major_radius=18.0 + math.sin(i) * 2.5,            # Natural finger pressure deformation
                    force=0.8 + math.sin(i * 0.5) * 0.2
                )
            )
        is_human, score, reason = self.validator.evaluate_touch_sample(points)
        self.assertTrue(is_human)
        self.assertGreaterEqual(score, 0.7)


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