#!/usr/bin/env python3
"""
Insider Threat Investigation Agent
Automates insider threat indicator collection by correlating SIEM data,
DLP alerts, access logs, and HR events to build investigation timelines.
"""

import csv
import hashlib
import json
import os
import sys
from datetime import datetime, timezone


def load_dlp_alerts(filepath: str) -> list[dict]:
    """Load DLP alert data from exported CSV."""
    alerts = []
    if not os.path.exists(filepath):
        print(f"[!] DLP alerts file not found: {filepath}")
        return alerts
    with open(filepath, "r", newline="") as f:
        reader = csv.DictReader(f)
        for row in reader:
            alerts.append({
                "timestamp": row.get("timestamp", ""),
                "user": row.get("user", ""),
                "policy": row.get("policy_name", ""),
                "action": row.get("action", ""),
                "destination": row.get("destination", ""),
                "file_count": int(row.get("file_count", 0)),
                "bytes_transferred": int(row.get("bytes_transferred", 0)),
                "severity": row.get("severity", "medium"),
            })
    return alerts


def load_access_logs(filepath: str) -> list[dict]:
    """Load authentication and access logs from exported JSON."""
    if not os.path.exists(filepath):
        print(f"[!] Access logs file not found: {filepath}")
        return []
    with open(filepath, "r") as f:
        return json.load(f)


def analyze_data_movement(dlp_alerts: list[dict], subject_user: str) -> dict:
    """Analyze data exfiltration indicators for the subject."""
    user_alerts = [a for a in dlp_alerts if a["user"].lower() == subject_user.lower()]

    total_bytes = sum(a["bytes_transferred"] for a in user_alerts)
    total_files = sum(a["file_count"] for a in user_alerts)
    destinations = {}
    for alert in user_alerts:
        dest = alert["destination"]
        destinations[dest] = destinations.get(dest, 0) + alert["file_count"]

    high_severity = [a for a in user_alerts if a["severity"] == "high"]

    return {
        "total_alerts": len(user_alerts),
        "total_bytes_transferred": total_bytes,
        "total_bytes_gb": round(total_bytes / (1024**3), 2),
        "total_files": total_files,
        "destinations": destinations,
        "high_severity_alerts": len(high_severity),
        "alert_details": user_alerts,
    }


def analyze_access_patterns(access_logs: list[dict], subject_user: str) -> dict:
    """Detect anomalous access patterns for the subject."""
    user_logs = [l for l in access_logs if l.get("user", "").lower() == subject_user.lower()]

    off_hours_events = []
    weekend_events = []
    unique_apps = set()
    unique_ips = set()

    for log in user_logs:
        ts = log.get("timestamp", "")
        try:
            dt = datetime.fromisoformat(ts.replace("Z", "+00:00"))
            hour = dt.hour
            weekday = dt.weekday()
            if hour < 7 or hour > 19:
                off_hours_events.append(log)
            if weekday >= 5:
                weekend_events.append(log)
        except (ValueError, AttributeError):
            pass

        unique_apps.add(log.get("application", "unknown"))
        unique_ips.add(log.get("source_ip", "unknown"))

    return {
        "total_events": len(user_logs),
        "off_hours_events": len(off_hours_events),
        "off_hours_pct": round(len(off_hours_events) / max(len(user_logs), 1) * 100, 1),
        "weekend_events": len(weekend_events),
        "weekend_pct": round(len(weekend_events) / max(len(user_logs), 1) * 100, 1),
        "unique_applications": sorted(unique_apps),
        "unique_source_ips": sorted(unique_ips),
    }


def detect_pre_departure_indicators(
    data_movement: dict, access_patterns: dict, notice_date: str
) -> list[dict]:
    """Identify pre-departure behavioral indicators."""
    indicators = []

    if data_movement["total_bytes_gb"] > 1.0:
        indicators.append({
            "severity": "HIGH",
            "indicator": "Bulk data transfer",
            "detail": f"{data_movement['total_bytes_gb']} GB transferred across {data_movement['total_files']} files",
        })

    if data_movement["high_severity_alerts"] > 0:
        indicators.append({
            "severity": "HIGH",
            "indicator": "High-severity DLP violations",
            "detail": f"{data_movement['high_severity_alerts']} high-severity DLP alerts triggered",
        })

    personal_storage = ["dropbox", "drive.google", "onedrive.live", "mega.nz", "wetransfer"]
    for dest, count in data_movement["destinations"].items():
        if any(ps in dest.lower() for ps in personal_storage):
            indicators.append({
                "severity": "HIGH",
                "indicator": "Transfer to personal cloud storage",
                "detail": f"{count} files sent to {dest}",
            })

    if access_patterns["off_hours_pct"] > 30:
        indicators.append({
            "severity": "MEDIUM",
            "indicator": "Elevated off-hours activity",
            "detail": f"{access_patterns['off_hours_pct']}% of activity outside business hours",
        })

    if access_patterns["weekend_pct"] > 15:
        indicators.append({
            "severity": "MEDIUM",
            "indicator": "Elevated weekend activity",
            "detail": f"{access_patterns['weekend_pct']}% of activity on weekends",
        })

    if len(access_patterns["unique_applications"]) > 15:
        indicators.append({
            "severity": "MEDIUM",
            "indicator": "Broad application access",
            "detail": f"Accessed {len(access_patterns['unique_applications'])} unique applications",
        })

    return indicators


def create_evidence_log(case_id: str, evidence_files: list[str]) -> dict:
    """Create chain-of-custody evidence log with file hashes."""
    items = []
    for filepath in evidence_files:
        if os.path.exists(filepath):
            with open(filepath, "rb") as f:
                content = f.read()
            items.append({
                "item_id": f"EV-{len(items)+1:03d}",
                "file": filepath,
                "sha256": hashlib.sha256(content).hexdigest(),
                "size_bytes": len(content),
                "collected_at": datetime.now(timezone.utc).isoformat(),
            })

    return {
        "case_id": case_id,
        "created_at": datetime.now(timezone.utc).isoformat(),
        "investigator": os.getenv("USER", "soc_analyst"),
        "evidence_items": items,
    }


def generate_report(case_id: str, subject: str, data_mv: dict, access: dict, indicators: list) -> str:
    """Generate insider threat investigation report."""
    lines = [
        f"INSIDER THREAT INVESTIGATION REPORT - {case_id}",
        "=" * 55,
        f"Subject: {subject}",
        f"Report Generated: {datetime.now(timezone.utc).strftime('%Y-%m-%d %H:%M UTC')}",
        "",
        "DATA MOVEMENT ANALYSIS:",
        f"  DLP Alerts: {data_mv['total_alerts']}",
        f"  Data Transferred: {data_mv['total_bytes_gb']} GB ({data_mv['total_files']} files)",
        f"  High-Severity Alerts: {data_mv['high_severity_alerts']}",
        f"  Destinations: {json.dumps(data_mv['destinations'], indent=4)}",
        "",
        "ACCESS PATTERN ANALYSIS:",
        f"  Total Events: {access['total_events']}",
        f"  Off-Hours Activity: {access['off_hours_pct']}%",
        f"  Weekend Activity: {access['weekend_pct']}%",
        f"  Applications Accessed: {len(access['unique_applications'])}",
        "",
        f"INDICATORS IDENTIFIED: {len(indicators)}",
        "-" * 40,
    ]
    for ind in indicators:
        lines.append(f"  [{ind['severity']}] {ind['indicator']}: {ind['detail']}")

    return "\n".join(lines)


if __name__ == "__main__":
    case_id = sys.argv[1] if len(sys.argv) > 1 else "IT-2024-0001"
    subject_user = sys.argv[2] if len(sys.argv) > 2 else "jsmith"
    dlp_file = sys.argv[3] if len(sys.argv) > 3 else "dlp_alerts.csv"
    access_file = sys.argv[4] if len(sys.argv) > 4 else "access_logs.json"

    print(f"[*] Starting insider threat investigation: {case_id}")
    print(f"[*] Subject: {subject_user}")

    dlp_alerts = load_dlp_alerts(dlp_file)
    access_logs = load_access_logs(access_file)

    data_movement = analyze_data_movement(dlp_alerts, subject_user)
    access_patterns = analyze_access_patterns(access_logs, subject_user)
    indicators = detect_pre_departure_indicators(data_movement, access_patterns, "2024-03-15")

    report = generate_report(case_id, subject_user, data_movement, access_patterns, indicators)
    print(report)

    output = f"insider_threat_{case_id}_{datetime.now(timezone.utc).strftime('%Y%m%d')}.json"
    with open(output, "w") as f:
        json.dump({"data_movement": data_movement, "access_patterns": access_patterns, "indicators": indicators}, f, indent=2)
    print(f"\n[*] Results saved to {output}")
