from pymisp import PyMISP
from datetime import datetime, timedelta
from collections import defaultdict
import urllib3
import os

# Experimental group 1 - low diversity
misp_url = os.getenv("MISP_URL_LOW_DIV", "https://20.56.140.119")
misp_key = os.getenv("MISP_KEY_LOW_DIV", "UdETf3kghPENVWwSriaL9rbA3GjPeEy8rM4coUaY")

# Experimental group 2 - high diversity
# misp_url = os.getenv("MISP_URL_HIGH_DIV", "https://20.86.130.191/")
# misp_key = os.getenv("MISP_KEY_HIGH_DIV", "RmXY9HUid2ZLF0c3RpJoMLfFawwWyvIquAkDOsjS")

misp_verify_cert = False  # Set to False because https errors
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) #Suppresses https error

# --- Initialize PyMISP ---
try:
    misp = PyMISP(misp_url, misp_key, misp_verify_cert)
    print("Connected to MISP.")
except Exception as e:
    print(f"Cannot connect to MISP: {e}")
    exit()

# Function returns disctionaries of IoCs and attributes for specified date
def get_iocs(misp_instance, exper_date):

    target_date = datetime.strptime(exper_date, '%Y-%m-%d').date()
    # Define the timestamp range for the single day
    timestamp_range = [target_date.strftime('%Y-%m-%d'), (target_date + timedelta(days=1)).strftime('%Y-%m-%d')]

    all_attributes = []
    page, limit = 1, 5000

    while True:
        try:
            attributes_page = misp_instance.search(controller='attributes', timestamp=timestamp_range,
                                                   page=page, limit=limit, pythonify=True)
            if not attributes_page: break
            all_attributes.extend(attributes_page)
            page += 1
        except Exception as e:
            print(f"Error fetching attributes page {page}: {e}")
            break

    unique_iocs_by_type = defaultdict(set)
    total_attributes_by_type = defaultdict(int)
    total_unique_iocs_set = set()

    for attr in all_attributes:
        # Attr will have 'value', 'type', 'timestamp' due to pythonify=True
        try: # Try converting timestamp, fall back to datetime object if already parsed
            attr_timestamp_dt = datetime.fromtimestamp(int(attr.timestamp))
        except (ValueError, TypeError):
            if isinstance(attr.timestamp, datetime):
                attr_timestamp_dt = attr.timestamp
            else: continue # Skip if timestamp is unparsable

        if attr_timestamp_dt.date() == target_date: # Process for exact target date
            ioc_tuple = (attr.value, attr.type)
            unique_iocs_by_type[attr.type].add(ioc_tuple)
            total_attributes_by_type[attr.type] += 1
            total_unique_iocs_set.add(ioc_tuple)

    return unique_iocs_by_type, len(total_unique_iocs_set), total_attributes_by_type

# Main execution
exper_date = "2025-07-15"  #Set experiment date

unique_iocs_by_type, total_unique_iocs_for_date, total_attributes_by_type = \
    get_iocs(misp, exper_date)

print(f"\n--- IoC Counts for Date: {exper_date} ---")

# Get all unique types found
sorted_types = sorted(list(unique_iocs_by_type.keys() | total_attributes_by_type.keys()))

if sorted_types:
    for attr_type in sorted_types:
        # Handle types that only have unique or total counts
        num_unique_iocs = len(unique_iocs_by_type.get(attr_type, set()))
        num_total_attributes = total_attributes_by_type.get(attr_type, 0)
        print(f"{attr_type}: {num_unique_iocs} : {num_total_attributes}")
else:
    print(f"No IoCs or attributes found.")

print(f"\nUnique IoCs (Overall for {exper_date}): {total_unique_iocs_for_date}")
print(f"Attributes (Overall for {exper_date}): {sum(total_attributes_by_type.values())}")