"""
Synthetic data generation receipts for TLM proof of concept.

Captures metadata about synthetic data generation runs including:
- Generator configuration (CTGAN params, seed, etc.)
- Realism validation metrics (KS statistics, correlation R²)
- Data quality parameters (missingness, noise, temporal structure)
- Cryptographic proof of generation parameters
"""

from __future__ import annotations

from typing import Any, Dict, List, Optional

from pydantic import Field

from receipts.base import BaseReceipt


class SyntheticRunReceipt(BaseReceipt):
    """
    Proof of synthetic data generation parameters.
    
    Captures all parameters used to generate synthetic clinical data,
    enabling perfect reproducibility and realism validation.
    """
    
    receipt_type: str = "SyntheticRunReceipt"
    
    # Generator configuration
    generator: str = Field(
        description="Generator type (simple, ctgan, temporal)"
    )
    generator_version: str = Field(
        default="1.0.0",
        description="Version of generator code"
    )
    source_distribution: str = Field(
        description="Source dataset (e.g., 'MIMIC_IV_v2.2')"
    )
    
    # Generation parameters
    n_generated: int = Field(
        description="Number of synthetic patients generated"
    )
    seed: int = Field(
        description="Random seed for reproducibility"
    )
    
    # CTGAN-specific (if applicable)
    ctgan_epochs: Optional[int] = Field(
        default=None,
        description="Number of CTGAN training epochs"
    )
    ctgan_training_samples: Optional[int] = Field(
        default=None,
        description="Number of real samples used for CTGAN training"
    )
    
    # Data quality parameters
    missingness_model: str = Field(
        description="Missingness model (e.g., 'MAR_0.1' for 10% MAR)"
    )
    missingness_rate: float = Field(
        description="Fraction of missing values (0.0-1.0)"
    )
    noise_model: str = Field(
        description="Noise model (e.g., 'Gaussian(σ=0.05)')"
    )
    noise_sigma: float = Field(
        description="Gaussian noise standard deviation"
    )
    temporal_model: str = Field(
        default="markov_first_order",
        description="Temporal structure model"
    )
    
    # Outcome prevalence
    sepsis_prevalence_target: float = Field(
        description="Target sepsis prevalence rate"
    )
    sepsis_prevalence_actual: float = Field(
        description="Actual sepsis rate in generated data"
    )
    
    # Realism validation metrics
    ks_statistics: Dict[str, float] = Field(
        default_factory=dict,
        description="Kolmogorov-Smirnov statistics per feature vs real data"
    )
    ks_max: Optional[float] = Field(
        default=None,
        description="Maximum KS statistic across all features"
    )
    ks_pass_threshold: float = Field(
        default=0.1,
        description="KS threshold for realism (typically 0.1)"
    )
    ks_passed: bool = Field(
        description="Whether all features pass KS threshold"
    )
    
    correlation_r2: Optional[float] = Field(
        default=None,
        description="R² of correlation matrix (synthetic vs real)"
    )
    correlation_pass_threshold: float = Field(
        default=0.9,
        description="R² threshold for correlation realism"
    )
    correlation_passed: bool = Field(
        description="Whether correlation passes threshold"
    )
    
    pca_overlap: Optional[float] = Field(
        default=None,
        description="PCA cluster overlap score (0.0-1.0)"
    )

    # Privacy risk assessment (Membership Inference Attacks)
    # See: https://pmc.ncbi.nlm.nih.gov/articles/PMC8766950/
    mia_risk_score: Optional[float] = Field(
        default=None,
        description="MIA attack success rate (0.0-1.0); lower is better"
    )
    mia_precision: Optional[float] = Field(
        default=None,
        description="MIA precision at 90% threshold"
    )
    mia_recall: Optional[float] = Field(
        default=None,
        description="MIA recall at 90% threshold"
    )
    privacy_posture: str = Field(
        default="fully_synthetic_external_ok",
        description="Privacy classification: fully_synthetic_external_ok, partially_synthetic_internal_only, or requires_review"
    )
    mia_test_size: Optional[int] = Field(
        default=None,
        description="Number of samples used in MIA audit"
    )

    # Adversarial cases (if included)
    adversarial_cases_included: int = Field(
        default=0,
        description="Number of adversarial cases for Guardian testing"
    )
    adversarial_case_types: List[str] = Field(
        default_factory=list,
        description="Types of adversarial cases (stale, contradictory, etc.)"
    )
    
    # Safety & compliance
    dignity_polyhedron: str = Field(
        description="Dignity configuration used (e.g., 'clinical_v1')"
    )
    hipaa_safe: bool = Field(
        default=True,
        description="All generated data is HIPAA-safe (no real PHI)"
    )
    
    # Computational metadata
    generation_time_seconds: float = Field(
        description="Wall-clock time to generate data"
    )
    training_time_seconds: Optional[float] = Field(
        default=None,
        description="Time to train CTGAN (if applicable)"
    )
    
    # Output metadata
    output_path: Optional[str] = Field(
        default=None,
        description="Path to generated data file"
    )
    output_format: str = Field(
        default="parquet",
        description="Output file format (parquet, csv, json)"
    )
    output_size_mb: Optional[float] = Field(
        default=None,
        description="Size of output file in MB"
    )
    
    # Validation summary
    realism_score: float = Field(
        description="Overall realism score (0.0-1.0) combining KS, correlation, PCA"
    )
    passes_all_checks: bool = Field(
        description="Whether synthetic data passes all realism checks"
    )
    
    def summary(self) -> str:
        """Generate human-readable summary of synthetic run."""
        return f"""
Synthetic Data Generation Summary
{'=' * 60}
Generator: {self.generator} v{self.generator_version}
Source: {self.source_distribution}

Generation:
  Patients: {self.n_generated:,}
  Seed: {self.seed}
  Sepsis Rate: {self.sepsis_prevalence_actual:.1%} (target: {self.sepsis_prevalence_target:.1%})
  Adversarial Cases: {self.adversarial_cases_included}

Data Quality:
  Missingness: {self.missingness_model} ({self.missingness_rate:.1%})
  Noise: {self.noise_model} (σ={self.noise_sigma})
  Temporal: {self.temporal_model}

Realism Validation:
  KS Max: {self.ks_max:.3f} (threshold: {self.ks_pass_threshold}) {'✓' if self.ks_passed else '✗'}
  Correlation R²: {self.correlation_r2:.3f} (threshold: {self.correlation_pass_threshold}) {'✓' if self.correlation_passed else '✗'}
  PCA Overlap: {self.pca_overlap:.3f if self.pca_overlap else 'N/A'}
  Overall Score: {self.realism_score:.3f}/1.00

Privacy Risk (MIA):
  Risk Score: {self.mia_risk_score:.3f if self.mia_risk_score else 'Not assessed'}
  Privacy Posture: {self.privacy_posture}
  {'✓ Safe for external sharing' if self.privacy_posture == 'fully_synthetic_external_ok' else '⚠ Internal use only' if 'internal_only' in self.privacy_posture else '⚠ Requires review'}

Performance:
  Generation Time: {self.generation_time_seconds:.1f}s
  Training Time: {self.training_time_seconds:.1f}s (if applicable)
  Output Size: {self.output_size_mb:.1f} MB

Status: {'✓ PASSED' if self.passes_all_checks else '✗ FAILED'} all realism checks
Receipt ID: {self.receipt_id}
{'=' * 60}
"""


__all__ = ["SyntheticRunReceipt"]
