import json
import logging
from typing import Dict, Any, List
from datetime import datetime

class CustomerProfiler:
    def __init__(self):
        self.profiles: Dict[str, Dict[str, Any]] = {}
        logging.basicConfig(level=logging.INFO)
        self.logger = logging.getLogger(__name__)

    def _initialize_profile(self, user_id: str) -> None:
        if user_id not in self.profiles:
            self.profiles[user_id] = {
                "user_id": user_id,
                "ips": set(),
                "isp_asn": set(),
                "geo_locations": set(),
                "hardware_fingerprints": set(),
                "credentials": [],
                "billing_metrics": {
                    "monthly_spend": 0.0,
                    "plan": "basic",
                    "payment_status": "unknown"
                },
                "last_seen": None
            }

    def ingest_telemetry(self, user_id: str, telemetry_data: Dict[str, Any]) -> None:
        """
        Ingests a telemetry event for a given user.
        Expected keys in telemetry_data:
        - ip: str
        - isp_asn: str
        - geo_location: str (e.g. "US-NY-NYC")
        - hardware_fingerprint: str
        - credential_validation_status: str
        - billing_update: dict (optional)
        """
        self._initialize_profile(user_id)
        profile = self.profiles[user_id]

        if "ip" in telemetry_data:
            profile["ips"].add(telemetry_data["ip"])
        if "isp_asn" in telemetry_data:
            profile["isp_asn"].add(telemetry_data["isp_asn"])
        if "geo_location" in telemetry_data:
            profile["geo_locations"].add(telemetry_data["geo_location"])
        if "hardware_fingerprint" in telemetry_data:
            profile["hardware_fingerprints"].add(telemetry_data["hardware_fingerprint"])
        if "credential_validation_status" in telemetry_data:
            profile["credentials"].append({
                "status": telemetry_data["credential_validation_status"],
                "timestamp": datetime.now().isoformat()
            })
        
        if "billing_update" in telemetry_data:
            billing = telemetry_data["billing_update"]
            if "monthly_spend" in billing:
                profile["billing_metrics"]["monthly_spend"] = billing["monthly_spend"]
            if "plan" in billing:
                profile["billing_metrics"]["plan"] = billing["plan"]
            if "payment_status" in billing:
                profile["billing_metrics"]["payment_status"] = billing["payment_status"]

        profile["last_seen"] = datetime.now().isoformat()
        self.logger.info(f"Updated profile for user {user_id}")

    def get_profile(self, user_id: str) -> Dict[str, Any]:
        """Returns the profile for a given user, with sets converted to lists for JSON serialization."""
        if user_id not in self.profiles:
            return {}
        
        profile = self.profiles[user_id].copy()
        profile["ips"] = list(profile["ips"])
        profile["isp_asn"] = list(profile["isp_asn"])
        profile["geo_locations"] = list(profile["geo_locations"])
        profile["hardware_fingerprints"] = list(profile["hardware_fingerprints"])
        return profile
    
    def export_all_profiles(self) -> str:
        """Exports all profiles as a JSON string."""
        serializable_profiles = {uid: self.get_profile(uid) for uid in self.profiles}
        return json.dumps(serializable_profiles, indent=4)

if __name__ == "__main__":
    profiler = CustomerProfiler()
    profiler.ingest_telemetry("user_123", {
        "ip": "192.168.1.1",
        "isp_asn": "AS12345",
        "geo_location": "US-CA-LA",
        "hardware_fingerprint": "hw_abc123",
        "credential_validation_status": "success",
        "billing_update": {
            "monthly_spend": 49.99,
            "plan": "premium",
            "payment_status": "active"
        }
    })
    print(profiler.export_all_profiles())
