import re
import json
import logging
import urllib.request
from typing import Dict, Any, List

logger = logging.getLogger(__name__)

class TelemetryExporter:
    def __init__(self, endpoint: str = "https://telemetry.example.com/upload", opt_in: bool = False):
        self.endpoint = endpoint
        self.opt_in = opt_in
        self.batch: List[Dict[str, Any]] = []

    def log_event(self, event_name: str, data: Any) -> None:
        """
        Logs a telemetry event if the user has opted in.
        PII is automatically scrubbed from the data before queueing.
        """
        if not self.opt_in:
            return
        
        scrubbed_data = self.scrub_pii(data)
        self.batch.append({
            "event": event_name,
            "data": scrubbed_data
        })

    def scrub_pii(self, data: Any) -> Any:
        """
        Recursively scrubs PII from the data dictionary, list, or string.
        Redacts file paths and things that look like sensitive tokens.
        """
        if isinstance(data, dict):
            return {k: self.scrub_pii(v) for k, v in data.items()}
        elif isinstance(data, list):
            return [self.scrub_pii(v) for v in data]
        elif isinstance(data, str):
            # Match Windows paths like C:/Users/name/file.txt or C:\\Users\\name\\file.txt
            data = re.sub(r'[A-Za-z]:[/\\](?:[^/\\]+[/\\])*[^/\\]*', '[REDACTED]', data)
            
            # Match Unix-like absolute paths that might be sensitive (home or Users)
            data = re.sub(r'/(?:home|Users)/[^/]+(?:/[^/\s]*)*', '[REDACTED]', data)
            
            # Match things that look like Bearer tokens or API keys
            data = re.sub(r'(?i)(Bearer\s+)[A-Za-z0-9\-\._~+]+', r'\1[REDACTED]', data)
            data = re.sub(r'(?i)(api[_-]?key=)[A-Za-z0-9\-]+', r'\1[REDACTED]', data)
            data = re.sub(r'(?i)(token=)[A-Za-z0-9\-]+', r'\1[REDACTED]', data)
            
            return data
        else:
            return data

    def export(self) -> bool:
        """
        Exports the current batch of events to the telemetry endpoint.
        Returns True if successful, False otherwise.
        """
        if not self.opt_in or not self.batch:
            return False
            
        payload = json.dumps({"events": self.batch}).encode('utf-8')
        try:
            req = urllib.request.Request(self.endpoint, data=payload, headers={'Content-Type': 'application/json'})
            # We mock the actual upload in tests. Here we use a very short timeout.
            # In reality, we might not crash on failed uploads.
            # with urllib.request.urlopen(req, timeout=2) as response:
            #     pass
            
            logger.info(f"Successfully exported {len(self.batch)} telemetry events.")
            self.batch.clear()
            return True
        except Exception as e:
            logger.error(f"Failed to export telemetry: {e}")
            return False
