"""
FREEEXILE INDEPENDENT SECURITY & ANTI-CHEAT OPERATIONS DIVISION (SEC-OPS CORE)
Master Architecture & Autonomous Security Auditing Engine.

Responsibilities:
1. Independent Security Authority & Release Veto Gate (Veto Power).
2. Automated Adversarial Red Team Fuzzing (Speedhack, Dupe, Replay, Tamper).
3. Real-Time Economic Anomaly & Primal Stone Ledger Auditing (Anti-Dupe).
4. Binary Integrity & Anti-Hooking / Jailbreak Verification.
5. Standardized ISO 27001 / OWASP MASVS Security Audit Reporting.
"""

from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
import time
import uuid
from typing import Dict, List, Optional, Set, Tuple, Any

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


class SeverityLevel(str, Enum):
    CRITICAL = "CRITICAL"
    HIGH = "HIGH"
    MEDIUM = "MEDIUM"
    LOW = "LOW"
    INFO = "INFO"


class AuditReportStatus(str, Enum):
    PASSED = "PASSED"
    VETOED = "VETOED"
    CONDITIONAL_PASS = "CONDITIONAL_PASS"


class SecurityVetoException(Exception):
    """Raised when an unpatched Critical or High vulnerability triggers an independent release veto."""
    pass


@dataclass(slots=True, frozen=True)
class SecurityVulnerability:
    vuln_id: str
    title: str
    severity: SeverityLevel
    component: str
    description: str
    proof_of_concept: str
    remediation: str
    timestamp: float = field(default_factory=time.time)


@dataclass(slots=True)
class SecurityAuditGate:
    """Independent Security Gate with VETO power.
    Enforces Zero-Tolerance for unpatched Critical and High security vulnerabilities.
    """
    findings: List[SecurityVulnerability] = field(default_factory=list)
    veto_thresholds: Set[SeverityLevel] = field(default_factory=lambda: {SeverityLevel.CRITICAL, SeverityLevel.HIGH})

    def record_vulnerability(self, vuln: SecurityVulnerability) -> None:
        self.findings.append(vuln)

    def has_veto_condition(self) -> bool:
        return any(v.severity in self.veto_thresholds for v in self.findings)

    def get_veto_findings(self) -> List[SecurityVulnerability]:
        return [v for v in self.findings if v.severity in self.veto_thresholds]

    def enforce_release_gate(self, build_id: str) -> bool:
        veto_issues = self.get_veto_findings()
        if veto_issues:
            issue_summary = ", ".join(f"[{v.severity.value}] {v.vuln_id}: {v.title}" for v in veto_issues)
            raise SecurityVetoException(
                f"INDEPENDENT SECURITY VETO TRIGGERED for Build '{build_id}'! "
                f"Found {len(veto_issues)} unpatched vulnerability/ies blocking release: {issue_summary}"
            )
        return True


@dataclass(slots=True, frozen=True)
class RedTeamAttackReport:
    attack_vector: str
    target_system: str
    is_blocked: bool
    defense_trigger: str
    suspicion_score: float = 0.0
    reconciled_coords: Optional[Tuple[float, float]] = None
    successful_purchases: int = 0
    blocked_purchases: int = 0
    item_duplicated: bool = False
    details: Dict[str, Any] = field(default_factory=dict)


class AutomatedRedTeamFuzzer:
    """Automated Adversarial Simulation Engine (Red Team Operator).
    Conducts penetration attacks against the game loop, gateway, and ledger.
    """

    def run_speedhack_injection_attack(
        self,
        player_id: int = 101,
        base_speed: float = 6.0,
        claimed_leap: float = 150.0,
        dt: float = 0.033
    ) -> RedTeamAttackReport:
        """Injects forged high-velocity leap coordinates to test Movement Authority."""
        engine = MovementAuthorityEngine(max_base_speed=base_speed)
        player = PlayerCharacter(entity_id=player_id, x=10.0, y=10.0, move_speed=base_speed)
        engine.register_player(player)

        valid, rx, ry = engine.validate_and_reconcile_position(
            entity_id=player_id,
            claimed_x=10.0 + claimed_leap,
            claimed_y=10.0,
            dt=dt
        )

        return RedTeamAttackReport(
            attack_vector="SPEEDHACK_POSITION_INJECTION",
            target_system="MovementAuthorityEngine",
            is_blocked=(not valid),
            defense_trigger="ServerReconciliation & Rubberband",
            suspicion_score=player.suspicion_score,
            reconciled_coords=(rx, ry)
        )

    def run_concurrent_dupe_attack(
        self,
        item_uuid: str,
        seller_id: str,
        buyer1_id: str,
        buyer2_id: str,
        price: int = 100
    ) -> RedTeamAttackReport:
        """Executes simultaneous buyout requests to exploit race conditions / double-spending."""
        engine = InstantBuyoutEngine()
        seller = engine.register_account(seller_id)
        b1 = engine.register_account(buyer1_id)
        b2 = engine.register_account(buyer2_id)

        b1.currencies["HonNguyen"] = price * 2
        b2.currencies["HonNguyen"] = price * 2

        item = StashItem(
            item_uuid=item_uuid,
            owner_account_id=seller_id,
            item_name="Hỗn Nguyên Thần Kiếm",
            asking_price_currency="HonNguyen",
            asking_price_amount=price
        )
        seller.items[item_uuid] = item

        # Simultaneous buyout simulation
        ok1, _, _ = engine.execute_instant_buyout(buyer1_id, seller_id, item_uuid, "HonNguyen", price)
        ok2, _, _ = engine.execute_instant_buyout(buyer2_id, seller_id, item_uuid, "HonNguyen", price)

        item_in_b1 = item_uuid in b1.items
        item_in_b2 = item_uuid in b2.items
        duplicated = item_in_b1 and item_in_b2

        return RedTeamAttackReport(
            attack_vector="TWO_PHASE_COMMIT_RACE_DUPE",
            target_system="InstantBuyoutEngine",
            is_blocked=(not duplicated and (ok1 != ok2)),
            defense_trigger="TwoPhaseCommit Mutex Lock",
            successful_purchases=1 if (ok1 or ok2) else 0,
            blocked_purchases=1 if (not ok1 or not ok2) else 0,
            item_duplicated=duplicated
        )

    def run_bitflip_tampering_attack(
        self,
        payload: bytes = b"ADD_CURRENCY_HON_NGUYEN_999999"
    ) -> RedTeamAttackReport:
        """Injects bit-flipped ciphertext to verify ChaCha20-Poly1305 MAC integrity."""
        engine = PacketCipherEngine(shared_key=b"SHARED_SECRET_KEY_FOR_TESTING_12")
        cipher, tag, nonce = engine.encrypt(payload, seq_num=1)

        # Bit-flip attack on first byte of ciphertext
        corrupted = bytes([cipher[0] ^ 0xFF]) + cipher[1:]

        blocked = False
        reason = "Undetected"
        try:
            engine.decrypt(corrupted, tag, nonce, seq_num=1)
        except ValueError as e:
            blocked = True
            reason = f"Corrupted MAC Signature or Tampered Ciphertext: {str(e)}"

        return RedTeamAttackReport(
            attack_vector="CIPHERTEXT_BITFLIP_INJECTION",
            target_system="PacketCipherEngine",
            is_blocked=blocked,
            defense_trigger=reason
        )

    def run_linear_bot_attack(self) -> RedTeamAttackReport:
        """Injects synthetic linear touch coordinates typical of PC emulators/macros."""
        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)
        return RedTeamAttackReport(
            attack_vector="SYNTHETIC_LINEAR_TOUCH_BOT",
            target_system="TouchBiometricsValidator",
            is_blocked=(not is_human),
            defense_trigger=reason,
            suspicion_score=1.0 - score
        )


@dataclass(slots=True)
class EconomicAnomalyDetector:
    """Autonomous Economic Auditor.
    Monitors currency velocity, detects duplication spikes, and triggers emergency quarantine.
    """
    max_hourly_currency_inflow: int = 5000
    account_inflows: Dict[str, int] = field(default_factory=dict)
    quarantined_accounts: Dict[str, Dict[str, Any]] = field(default_factory=dict)

    def record_inflow(self, account_id: str, currency: str, amount: int) -> bool:
        current = self.account_inflows.get(account_id, 0)
        new_total = current + amount
        self.account_inflows[account_id] = new_total

        if new_total > self.max_hourly_currency_inflow:
            self._trigger_emergency_quarantine(account_id, currency, new_total)
            return False
        return True

    def _trigger_emergency_quarantine(self, account_id: str, currency: str, total_inflow: int) -> None:
        self.quarantined_accounts[account_id] = {
            "account_id": account_id,
            "currency": currency,
            "inflow_amount": total_inflow,
            "status": "LOCKED_FOR_AUDIT",
            "timestamp": time.time(),
            "reason": f"Abnormal currency velocity: {total_inflow} > {self.max_hourly_currency_inflow} threshold"
        }

    def is_quarantined(self, account_id: str) -> bool:
        return account_id in self.quarantined_accounts

    def get_quarantine_record(self, account_id: str) -> Optional[Dict[str, Any]]:
        return self.quarantined_accounts.get(account_id)

    def lift_quarantine(self, account_id: str, auditor_token: str) -> bool:
        if auditor_token.startswith("SEC_AUTH_") and account_id in self.quarantined_accounts:
            del self.quarantined_accounts[account_id]
            self.account_inflows[account_id] = 0
            return True
        return False


@dataclass(slots=True, frozen=True)
class BinaryAttestationResult:
    is_trusted: bool
    bundle_id: str
    violation_flags: List[str]
    audit_timestamp: float = field(default_factory=time.time)


class BinaryIntegrityAttestor:
    """Mobile & Binary Security Auditor.
    Verifies App Attest integrity, bundle signature, debugger attachment, and jailbreak hooks.
    """
    def __init__(self, expected_bundle_id: str = "com.freeexile.game.ios") -> None:
        self.expected_bundle_id = expected_bundle_id

    def verify_client_environment(
        self,
        bundle_id: str,
        has_jailbreak_artifacts: bool,
        is_debugger_attached: bool,
        signature_fingerprint: str
    ) -> BinaryAttestationResult:
        violations: List[str] = []

        if bundle_id != self.expected_bundle_id:
            violations.append("BUNDLE_ID_MISMATCH")

        if has_jailbreak_artifacts:
            violations.append("JAILBREAK_DETECTED")

        if is_debugger_attached:
            violations.append("DEBUGGER_ATTACHED")

        if not signature_fingerprint.startswith("SHA256:OFFICIAL_APPLE_CERT"):
            violations.append("INVALID_SIGNATURE_FINGERPRINT")

        is_trusted = len(violations) == 0
        return BinaryAttestationResult(
            is_trusted=is_trusted,
            bundle_id=bundle_id,
            violation_flags=violations
        )


@dataclass(slots=True)
class ConsolidatedAuditReport:
    audit_id: str
    build_version: str
    environment: str
    status: AuditReportStatus
    tests_executed: int
    critical_count: int
    high_count: int
    medium_count: int
    low_count: int
    attack_results: List[RedTeamAttackReport] = field(default_factory=list)
    vulnerabilities: List[SecurityVulnerability] = field(default_factory=list)
    timestamp: float = field(default_factory=time.time)

    def to_markdown(self) -> str:
        status_badge = "🟢 ĐẠT CHUẨN (PASSED)" if self.status == AuditReportStatus.PASSED else "🔴 PHỦ QUYẾT (VETOED)"
        lines = [
            f"# BÁO CÁO KIỂM TOÁN AN NINH ĐỘC LẬP (SEC-OPS AUDIT REPORT)",
            f"> **Audit ID**: `{self.audit_id}`  ",
            f"> **Phiên bản Build**: `{self.build_version}` | **Môi trường**: `{self.environment}`  ",
            f"> **Phán quyết An ninh**: **{status_badge}**  ",
            f"> **Thời gian thẩm định**: `{time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.timestamp))}`  ",
            "",
            "## 1. TỔNG HỢP KẾT QUẢ KIỂM THỬ BẢO MẬT",
            f"- **Tổng số ca tấn công mô phỏng**: `{self.tests_executed}`",
            f"- **Lỗ hổng Critical**: `{self.critical_count}` (Ngưỡng Veto: > 0)",
            f"- **Lỗ hổng High**: `{self.high_count}` (Ngưỡng Veto: > 0)",
            f"- **Lỗ hổng Medium**: `{self.medium_count}`",
            f"- **Lỗ hổng Low/Info**: `{self.low_count}`",
            "",
            "## 2. NHẬT KÝ TÁC CHIẾN RED TEAM (AUTOMATED ADVERSARIAL ATTACKS)",
            "| Vector Tấn Công | Mục Tiêu | Kết Quả Ngăn Chặn | Cơ Chế Phòng Thủ Kích Hoạt |",
            "| :--- | :--- | :--- | :--- |"
        ]
        for att in self.attack_results:
            blocked_str = "✅ ĐÃ CHẶN ĐỨNG" if att.is_blocked else "❌ BỊ XÂM NHẬP"
            lines.append(f"| `{att.attack_vector}` | `{att.target_system}` | {blocked_str} | {att.defense_trigger} |")

        lines.extend([
            "",
            "## 3. PHÁN QUYẾT CỦA KHỐI BẢO MẬT & CHỐNG GIAN LẬN (SEC-OPS MANDATE)",
            f"- **Cổng An ninh (Security Gate)**: {'CHO PHÉP PHÁT HÀNH' if self.status == AuditReportStatus.PASSED else 'KÍCH HOẠT QUYỀN VETO PHỦ QUYẾT BẢN BUILD'}.",
            "- **Cơ chế**: Tuân thủ nghiêm ngặt Hiến chương An toàn Thông tin Độc lập 2026."
        ])
        return "\n".join(lines)


class IndependentSecurityAuditor:
    """Master Coordinator for the Independent Security & Anti-Cheat Division."""

    def __init__(self) -> None:
        self.gate = SecurityAuditGate()
        self.fuzzer = AutomatedRedTeamFuzzer()
        self.economic_detector = EconomicAnomalyDetector()
        self.binary_attestor = BinaryIntegrityAttestor()

    def execute_full_security_audit(
        self,
        build_version: str = "2026.1-STAGING",
        environment: str = "STAGING"
    ) -> ConsolidatedAuditReport:
        audit_id = f"AUDIT-{uuid.uuid4().hex[:8].upper()}"
        attacks: List[RedTeamAttackReport] = []

        # 1. Run Speedhack injection attack
        a1 = self.fuzzer.run_speedhack_injection_attack()
        attacks.append(a1)

        # 2. Run Dupe Double-Spend attack
        a2 = self.fuzzer.run_concurrent_dupe_attack(
            item_uuid="audit_dupe_item_01",
            seller_id="seller_test",
            buyer1_id="buyer_test_1",
            buyer2_id="buyer_test_2"
        )
        attacks.append(a2)

        # 3. Run Bit-flip tampering attack
        a3 = self.fuzzer.run_bitflip_tampering_attack()
        attacks.append(a3)

        # 4. Run Synthetic Linear Bot attack
        a4 = self.fuzzer.run_linear_bot_attack()
        attacks.append(a4)

        # Evaluate pass/fail conditions
        unblocked_attacks = [a for a in attacks if not a.is_blocked]
        for ua in unblocked_attacks:
            self.gate.record_vulnerability(
                SecurityVulnerability(
                    vuln_id=f"VULN-{uuid.uuid4().hex[:6].upper()}",
                    title=f"Unblocked Attack Vector: {ua.attack_vector}",
                    severity=SeverityLevel.CRITICAL,
                    component=ua.target_system,
                    description=f"Defense mechanism failed to mitigate {ua.attack_vector}",
                    proof_of_concept=str(ua.details),
                    remediation="Reinforce server-authoritative validations"
                )
            )

        crit_count = sum(1 for v in self.gate.findings if v.severity == SeverityLevel.CRITICAL)
        high_count = sum(1 for v in self.gate.findings if v.severity == SeverityLevel.HIGH)
        med_count = sum(1 for v in self.gate.findings if v.severity == SeverityLevel.MEDIUM)
        low_count = sum(1 for v in self.gate.findings if v.severity in (SeverityLevel.LOW, SeverityLevel.INFO))

        status = AuditReportStatus.PASSED if not self.gate.has_veto_condition() else AuditReportStatus.VETOED

        return ConsolidatedAuditReport(
            audit_id=audit_id,
            build_version=build_version,
            environment=environment,
            status=status,
            tests_executed=len(attacks),
            critical_count=crit_count,
            high_count=high_count,
            medium_count=med_count,
            low_count=low_count,
            attack_results=attacks,
            vulnerabilities=self.gate.findings
        )
