#!/usr/bin/env python3
"""Ransomware Playbook Automation Agent - Automates SOC ransomware response steps."""

import json
import logging
import os
import argparse
import hashlib
from datetime import datetime

import requests

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger(__name__)


def check_id_ransomware(sample_path):
    """Upload encrypted file sample to ID Ransomware for variant identification."""
    url = "https://id-ransomware.malwarehunterteam.com/index.php"
    with open(sample_path, "rb") as f:
        files = {"sampleUpload": (sample_path, f)}
        resp = requests.post(url, files=files, timeout=60)
    logger.info("ID Ransomware response status: %d", resp.status_code)
    return resp.text


def query_nomoreransom(ransomware_family):
    """Check No More Ransom Project for available decryptors."""
    url = f"https://www.nomoreransom.org/en/decryption-tools.html"
    resp = requests.get(url, timeout=30)
    if ransomware_family.lower() in resp.text.lower():
        logger.info("Decryptor may be available for %s on No More Ransom", ransomware_family)
        return True
    logger.info("No decryptor found for %s", ransomware_family)
    return False


def query_malwarebazaar_hash(file_hash):
    """Query MalwareBazaar for IOC details by SHA-256 hash."""
    url = "https://mb-api.abuse.ch/api/v1/"
    data = {"query": "get_info", "hash": file_hash}
    resp = requests.post(url, data=data, timeout=30)
    result = resp.json()
    if result.get("query_status") == "ok":
        sample = result["data"][0]
        logger.info(
            "MalwareBazaar match: %s (family: %s)",
            sample.get("sha256_hash"),
            sample.get("signature"),
        )
        return sample
    return None


def isolate_host_crowdstrike(api_base, token, device_id):
    """Isolate a compromised host via CrowdStrike Falcon API."""
    headers = {"Authorization": f"Bearer {token}", "Content-Type": "application/json"}
    resp = requests.post(
        f"{api_base}/devices/entities/devices-actions/v2?action_name=contain",
        headers=headers,
        json={"ids": [device_id]},
        timeout=30,
    )
    resp.raise_for_status()
    logger.info("Host %s isolated via CrowdStrike", device_id)
    return resp.json()


def search_iocs_splunk(splunk_url, session_key, ioc_list):
    """Search Splunk for IOC matches across the enterprise."""
    ioc_query = " OR ".join([f'"{ioc}"' for ioc in ioc_list])
    query = (
        f"search index=sysmon (EventCode=1 OR EventCode=11 OR EventCode=3) ({ioc_query}) "
        "| stats count by Computer, EventCode, Image, CommandLine | sort - count"
    )
    resp = requests.post(
        f"{splunk_url}/services/search/jobs",
        headers={"Authorization": f"Splunk {session_key}"},
        data={"search": f"search {query}", "output_mode": "json"},
        verify=not os.environ.get("SKIP_TLS_VERIFY", "").lower() == "true",  # Set SKIP_TLS_VERIFY=true for self-signed certs in lab environments
        timeout=30,
    )
    return resp.json()


def generate_ir_report(incident_id, variant, affected_hosts, containment_actions, iocs):
    """Generate a structured ransomware incident response report."""
    report = {
        "incident_id": incident_id,
        "timestamp": datetime.utcnow().isoformat(),
        "ransomware_variant": variant,
        "affected_hosts": affected_hosts,
        "containment_actions": containment_actions,
        "indicators_of_compromise": iocs,
        "phases": {
            "detection": "Completed",
            "containment": "Completed" if containment_actions else "Pending",
            "eradication": "Pending",
            "recovery": "Pending",
        },
    }
    print(json.dumps(report, indent=2))
    return report


def collect_iocs_from_sample(sample_path):
    """Extract IOCs from a ransomware sample file hash."""
    with open(sample_path, "rb") as f:
        content = f.read()
    sha256 = hashlib.sha256(content).hexdigest()
    md5 = hashlib.md5(content).hexdigest()
    logger.info("Sample SHA-256: %s", sha256)
    logger.info("Sample MD5: %s", md5)

    bazaar_info = query_malwarebazaar_hash(sha256)
    iocs = {"sha256": sha256, "md5": md5}
    if bazaar_info:
        iocs["family"] = bazaar_info.get("signature", "unknown")
        iocs["tags"] = bazaar_info.get("tags", [])
    return iocs


def main():
    parser = argparse.ArgumentParser(description="Ransomware Playbook Automation Agent")
    parser.add_argument("--incident-id", required=True, help="Incident ticket ID")
    parser.add_argument("--sample", help="Path to encrypted file sample")
    parser.add_argument("--device-id", help="CrowdStrike device ID for isolation")
    parser.add_argument("--cs-token", help="CrowdStrike API bearer token")
    parser.add_argument("--splunk-url", help="Splunk management URL")
    parser.add_argument("--splunk-key", help="Splunk session key")
    parser.add_argument("--output", default="ransomware_ir_report.json")
    args = parser.parse_args()

    iocs = {}
    variant = "Unknown"
    containment_actions = []

    if args.sample:
        iocs = collect_iocs_from_sample(args.sample)
        variant = iocs.get("family", "Unknown")
        query_nomoreransom(variant)

    if args.device_id and args.cs_token:
        isolate_host_crowdstrike(
            "https://api.crowdstrike.com", args.cs_token, args.device_id
        )
        containment_actions.append(f"Isolated device {args.device_id} via CrowdStrike")

    if args.splunk_url and args.splunk_key and iocs:
        search_iocs_splunk(args.splunk_url, args.splunk_key, [iocs.get("sha256", "")])

    report = generate_ir_report(
        args.incident_id, variant, [args.device_id] if args.device_id else [], containment_actions, iocs
    )
    with open(args.output, "w") as f:
        json.dump(report, f, indent=2)
    logger.info("IR report saved to %s", args.output)


if __name__ == "__main__":
    main()
