#!/usr/bin/env python3
"""
VIGILORY X — CUSTOMER DEMO COMMAND CONSOLE
Simulation-only demonstration environment.

This program performs NO real network, endpoint, identity, cloud, or OT actions.
All detections, blocks, approvals, recoveries, and notifications are simulated.
"""

from __future__ import annotations

import os
import sys
import time
import random
from dataclasses import dataclass, field
from datetime import datetime, timezone
from typing import List, Dict, Optional

APP_NAME = "VIGILORY X"
VERSION = "DEMO CONSOLE v1.0"
SIMULATION_ONLY = True

# ---------------------------------------------------------------------
# Console helpers
# ---------------------------------------------------------------------

def now():
    return datetime.now().strftime("%H:%M:%S")

def utc_now():
    return datetime.now(timezone.utc).isoformat()

def clear():
    os.system("cls" if os.name == "nt" else "clear")

def line(ch="=", n=78):
    print(ch * n)

def slow(text, delay=0.012):
    for c in text:
        print(c, end="", flush=True)
        time.sleep(delay)
    print()

def pause(sec=0.5):
    time.sleep(sec)

def status(label, message, tag="INFO"):
    print(f"[{now()}] [{tag:<8}] {label:<22} {message}")

def prompt(label, default=""):
    suffix = f" [{default}]" if default else ""
    value = input(f"{label}{suffix}: ").strip()
    return value or default

# ---------------------------------------------------------------------
# Data types
# ---------------------------------------------------------------------

@dataclass
class DemoCustomer:
    organization: str
    contact_name: str
    environment: str
    primary_or_secondary: str
    industry: str
    assets: int
    has_ot: bool
    current_stack: str

@dataclass
class DemoEvent:
    event_id: str
    severity: str
    domain: str
    title: str
    target: str
    authority: str
    action: str
    reversible: bool
    approval_required: bool
    status: str = "PENDING"
    details: List[str] = field(default_factory=list)

@dataclass
class AuditRecord:
    ts: str
    event_id: str
    action: str
    result: str
    actor: str
    detail: str

# ---------------------------------------------------------------------
# Demo content
# ---------------------------------------------------------------------

def build_scenario(customer: DemoCustomer) -> List[DemoEvent]:
    events = [
        DemoEvent(
            "VX-1001", "MEDIUM", "IDENTITY",
            "Anomalous privileged sign-in pattern",
            "ENG-USER-4471", "A0",
            "Observe and correlate identity activity",
            True, False,
            details=[
                "New source location differs from established identity baseline",
                "Session token age inconsistent with normal behavior",
                "Endpoint context requested from EDR"
            ],
        ),
        DemoEvent(
            "VX-1002", "HIGH", "ENDPOINT",
            "Suspicious PowerShell execution chain",
            "WS-ENG-204", "A1",
            "Isolate non-critical corporate workstation",
            True, False,
            details=[
                "Encoded PowerShell observed",
                "Credential-access behavior correlated",
                "SMB discovery attempts detected"
            ],
        ),
        DemoEvent(
            "VX-1003", "HIGH", "IDENTITY",
            "Session linked to confirmed endpoint compromise",
            "ENG-USER-4471", "A1",
            "Revoke suspicious identity session",
            True, False,
            details=[
                "Identity session linked to isolated endpoint",
                "Risk score exceeds configured A1 threshold"
            ],
        ),
        DemoEvent(
            "VX-1004", "CRITICAL", "CLOUD",
            "Unauthorized service-principal persistence",
            "SPN-BUILD-884", "A2",
            "Disable unauthorized service principal",
            True, True,
            details=[
                "Credential created outside approved change window",
                "Build artifact access observed",
                "Administrative approval required before write action"
            ],
        ),
    ]

    if customer.has_ot:
        events.append(
            DemoEvent(
                "VX-1005", "CRITICAL", "OT/ICS",
                "Enterprise-to-OT pivot attempt",
                "OT-JUMP-07", "A3",
                "Block enterprise path and escalate OT action",
                True, True,
                details=[
                    "Engineering workstation reached OT jump host",
                    "Industrial asset discovery detected",
                    "Direct PLC action remains outside autonomous authority"
                ],
            )
        )

    events += [
        DemoEvent(
            "VX-1006", "LOW", "NETWORK",
            "Known malicious indicator observed at proxy",
            "203.0.113.50", "A1",
            "Block indicator at enterprise proxy",
            True, False,
            details=[
                "Threat-intelligence confidence: 0.93",
                "No protected OT/ICS target associated with indicator"
            ],
        ),
        DemoEvent(
            "VX-1007", "INFO", "RECOVERY",
            "Post-response validation",
            "ENVIRONMENT", "A0",
            "Verify containment and return safe state",
            True, False,
            details=[
                "Endpoint isolation verified",
                "Identity session invalidated",
                "Proxy block confirmed",
                "Outstanding approval-gated actions reviewed"
            ],
        ),
    ]
    return events

# ---------------------------------------------------------------------
# Simulation logic
# ---------------------------------------------------------------------

class VigiloryXDemo:
    def __init__(self, customer: DemoCustomer):
        self.customer = customer
        self.events = build_scenario(customer)
        self.audit: List[AuditRecord] = []
        self.approved = 0
        self.denied = 0
        self.auto_actions = 0
        self.observed = 0

    def audit_add(self, event: DemoEvent, action: str, result: str, actor: str, detail: str):
        self.audit.append(AuditRecord(
            ts=utc_now(),
            event_id=event.event_id,
            action=action,
            result=result,
            actor=actor,
            detail=detail
        ))

    def boot(self):
        clear()
        line()
        print(f"{APP_NAME:^78}")
        print(f"{VERSION:^78}")
        print(f"{'SIMULATION MODE — NO REAL ACTIONS ARE PERFORMED':^78}")
        line()
        status("Customer", self.customer.organization, "READY")
        status("Deployment Model", self.customer.primary_or_secondary, "READY")
        status("Environment", self.customer.environment, "READY")
        status("Security Stack", self.customer.current_stack, "READY")
        status("Protected Assets", f"{self.customer.assets:,}", "READY")
        status("OT/ICS Present", "YES" if self.customer.has_ot else "NO", "READY")
        print()
        slow("Initializing evidence plane, identity verification, policy engine and response simulation...", 0.006)
        pause(0.6)
        for component in [
            "Telemetry ingestion",
            "Identity verification service",
            "Signed evidence envelope",
            "Campaign correlator",
            "A0-A4 policy engine",
            "Response capability broker",
            "Audit and recovery services",
        ]:
            status("INITIALIZE", component, "OK")
            pause(0.18)
        print()
        status("SYSTEM", "Vigilory X demo environment is operational.", "ONLINE")
        line()

    def show_event(self, ev: DemoEvent):
        print()
        line("-")
        print(f"EVENT {ev.event_id} | {ev.severity} | {ev.domain}")
        print(f"Threat : {ev.title}")
        print(f"Target : {ev.target}")
        print(f"Policy : {ev.authority}")
        print(f"Action : {ev.action}")
        print("Evidence:")
        for d in ev.details:
            print(f"  - {d}")
            pause(0.12)

    def simulate_observe(self, ev: DemoEvent):
        status("EVIDENCE", "Signed evidence envelope created", "VERIFIED")
        status("IDENTITY", "Source and actor provenance evaluated", "VERIFIED")
        status("POLICY", f"{ev.authority} permits observation only", "A0")
        status("RESPONSE", "No external state change performed", "OBSERVE")
        ev.status = "OBSERVED"
        self.observed += 1
        self.audit_add(ev, ev.action, "OBSERVED", "VIGILORY-X", "A0 observation complete")

    def simulate_a1(self, ev: DemoEvent):
        status("POLICY", "Target class and reversible-action policy checked", "PASS")
        status("EVIDENCE", "Evidence confidence above configured threshold", "PASS")
        status("CAPABILITY", "Short-lived A1 capability issued", "ISSUED")
        pause(0.4)
        status("ACTION", f"{ev.action} -> {ev.target}", "RUNNING")
        pause(0.7)
        status("CONNECTOR", "Authorization revalidated at execution point", "PASS")
        pause(0.3)
        status("ACTION", f"{ev.action} -> {ev.target}", "SUCCESS")
        status("VERIFY", "Expected postcondition confirmed", "SAFE")
        status("ROLLBACK", "Rollback reference retained", "READY")
        ev.status = "SUCCESS"
        self.auto_actions += 1
        self.audit_add(ev, ev.action, "SUCCESS", "VIGILORY-X/A1", "Reversible autonomous response")

    def ask_admin_approval(self, ev: DemoEvent):
        status("POLICY", f"{ev.authority} requires external approval", "HOLD")
        status("ADMIN", "Security administrator notified", "NOTIFIED")
        status("ADMIN", "Waiting for approve / deny decision", "WAITING")
        print()
        print("Demo approval decision:")
        print("  [A] Approve")
        print("  [D] Deny")
        print("  [T] Timeout / no response")
        choice = input("Decision [A/D/T]: ").strip().upper() or "A"

        if choice == "A":
            status("APPROVAL", "Administrator identity verified", "VERIFIED")
            status("APPROVAL", "Signed approval envelope received", "APPROVED")
            status("CAPABILITY", f"{ev.authority} capability issued", "ISSUED")
            status("ACTION", f"{ev.action} -> {ev.target}", "RUNNING")
            pause(0.8)
            if ev.domain == "OT/ICS":
                status("SAFETY", "Protected OT target remains outside direct automation", "ENFORCED")
                status("ACTION", "Enterprise-side containment completed", "SUCCESS")
                status("ESCALATION", "OT operator review remains active", "PENDING")
            else:
                status("ACTION", f"{ev.action} -> {ev.target}", "SUCCESS")
                status("VERIFY", "Expected postcondition confirmed", "SAFE")
            ev.status = "APPROVED_SUCCESS"
            self.approved += 1
            self.audit_add(ev, ev.action, "APPROVED_SUCCESS", "DEMO-ADMIN", "Signed approval simulated")
        elif choice == "D":
            status("APPROVAL", "Administrator denied requested action", "DENIED")
            status("POLICY", "Capability issuance blocked", "ENFORCED")
            status("RESPONSE", "Finding retained for analyst follow-up", "PENDING")
            ev.status = "DENIED"
            self.denied += 1
            self.audit_add(ev, ev.action, "DENIED", "DEMO-ADMIN", "Admin denied action")
        else:
            status("APPROVAL", "No approval received before demo timeout", "TIMEOUT")
            status("POLICY", "No capability issued", "ENFORCED")
            status("RESPONSE", "Case escalated to human review queue", "PENDING")
            ev.status = "TIMEOUT"
            self.audit_add(ev, ev.action, "TIMEOUT", "VIGILORY-X", "No approval received")

    def process(self):
        print()
        status("SYSTEM", "Demo detection and response sequence started", "RUNNING")
        for ev in self.events:
            self.show_event(ev)
            pause(0.3)
            if ev.authority == "A0":
                self.simulate_observe(ev)
            elif ev.authority == "A1":
                self.simulate_a1(ev)
            elif ev.approval_required:
                self.ask_admin_approval(ev)
            pause(0.5)

    def summary(self):
        print()
        line()
        print("DEMO MISSION SUMMARY")
        line()
        print(f"Organization                  : {self.customer.organization}")
        print(f"Events processed              : {len(self.events)}")
        print(f"A0 observations               : {self.observed}")
        print(f"A1 autonomous actions         : {self.auto_actions}")
        print(f"Admin approvals               : {self.approved}")
        print(f"Admin denials                 : {self.denied}")
        print(f"Audit records                 : {len(self.audit)}")
        print()
        status("SYSTEM", "No unauthorized or real external actions were performed.", "SAFE")
        status("SYSTEM", "Evidence and simulated audit trail retained for this session.", "COMPLETE")
        line()

        print("\nAudit trail:")
        for r in self.audit:
            print(f"  {r.ts} | {r.event_id} | {r.result:<18} | {r.actor:<16} | {r.action}")

        print()
        slow("Vigilory X demonstration complete.", 0.02)

# ---------------------------------------------------------------------
# Customer onboarding
# ---------------------------------------------------------------------

def gather_customer() -> DemoCustomer:
    clear()
    line()
    print(f"{'VIGILORY X CUSTOMER DEMONSTRATION':^78}")
    print(f"{'SIMULATION ONLY':^78}")
    line()
    print("This demo will ask for high-level environment information only.")
    print("Do not enter passwords, API keys, CUI, classified data, or sensitive security details.")
    print()

    organization = prompt("Organization", "Demo Customer")
    contact = prompt("Your name", "Demo User")
    environment = prompt("Environment", "Hybrid Enterprise")
    mode = prompt("Primary or secondary defense", "Secondary Defense")
    industry = prompt("Industry", "Manufacturing")
    assets_raw = prompt("Approximate protected asset count", "2500")
    try:
        assets = max(1, int(assets_raw.replace(",", "")))
    except ValueError:
        assets = 2500
    ot_raw = prompt("OT/ICS environment present? (yes/no)", "yes").lower()
    has_ot = ot_raw.startswith("y")
    current_stack = prompt("Current security stack", "SIEM + EDR + IdP + Network Security")

    return DemoCustomer(
        organization=organization,
        contact_name=contact,
        environment=environment,
        primary_or_secondary=mode,
        industry=industry,
        assets=assets,
        has_ot=has_ot,
        current_stack=current_stack
    )

def main():
    customer = gather_customer()
    demo = VigiloryXDemo(customer)
    print("\nStarting simulation...")
    time.sleep(1.0)
    demo.boot()
    input("\nPress ENTER to begin the simulated threat sequence...")
    demo.process()
    demo.summary()

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n\nDemo interrupted by user.")
        sys.exit(0)
