import json
import io
from pathlib import Path
from datetime import datetime, timezone
import contextlib

from marco.core.repository import resolve_version
from marco.reproducibility_proof.verify import verify
from marco.reproducibility_proof.canonicalizer import detect_stochastic_ops

def evaluate_version(version_ref: str, repo_path: Path) -> dict:
    repo_path = Path(repo_path)
    vid = resolve_version(version_ref, repo_path)
    
    version_dir = repo_path / '.marco' / 'versions' / vid
    manifest_path = version_dir / 'manifest.json'
    post_stats_path = version_dir / 'post_stats.json'
    
    if not manifest_path.exists():
        raise ValueError(f"Manifest not found for version {vid}")
        
    manifest = json.loads(manifest_path.read_text(encoding='utf-8'))
    dag_config = manifest.get('dag', {})
    
    # 1. Pipeline Determinism Grade
    stochastic_warnings = detect_stochastic_ops(dag_config)
    determinism_grade = "F" if stochastic_warnings else "A"
    
    # 2. Reproducibility Confidence Score (RCS)
    f = io.StringIO()
    with contextlib.redirect_stdout(f):
        # We run verify silently to check its actual current state
        passed = verify(vid, repo_path)
    
    output = f.getvalue()
    env_changed = "Environment has changed" in output
    
    if not passed:
        rcs = "0%"
    elif stochastic_warnings:
        rcs = "50%"
    elif env_changed:
        rcs = "75%"
    else:
        rcs = "100%"
        
    # 3. Data Volatility Index (DVI)
    dvi = 0.0
    if post_stats_path.exists():
        stats = json.loads(post_stats_path.read_text(encoding='utf-8'))
        doc_pct = stats.get('documents_removed_pct', 0.0)
        tok_pct = stats.get('token_reduction_pct', 0.0)
        # Simple heuristic: average of doc and token reduction percentages
        dvi = round((doc_pct + tok_pct) / 200.0, 2)
        dvi = max(0.0, min(1.0, dvi))
        
    # Generate Insights
    insights = []
    if determinism_grade == "A":
        insights.append("✅ No stochastic (random) operations detected. Pipeline is structurally deterministic.")
    else:
        insights.append(f"⚠️ Pipeline contains unseeded stochastic operations: {', '.join(stochastic_warnings)}")
        
    if passed and not env_changed:
        insights.append("✅ Mathematical Reproducibility Proof passed perfectly on the current environment.")
    elif passed and env_changed:
        insights.append("⚠️ Reproducibility Proof passed, but the underlying environment (Python/dependencies) has changed.")
    else:
        insights.append("❌ Reproducibility Proof FAILED. Data hashes do not match the pipeline output.")
        
    if dvi > 0.5:
        insights.append(f"⚠️ High volatility ({int(dvi*100)}%): The preprocessing pipeline radically mutated or reduced the raw data. Ensure critical signals were not lost.")
    elif dvi > 0.1:
        insights.append(f"ℹ️ Moderate volatility ({int(dvi*100)}%): The pipeline noticeably reduced data footprint.")
    else:
        insights.append(f"✅ Low volatility ({int(dvi*100)}%): The processing is lightweight and retains most original data structure.")
        
    overall = "EXCELLENT"
    if not passed:
        overall = "BROKEN"
    elif rcs in ["50%", "75%"] or dvi > 0.6:
        overall = "WARNING"
        
    report = {
        "version_id": vid,
        "evaluated_at": datetime.now(timezone.utc).isoformat().replace('+00:00', 'Z'),
        "overall_health_status": overall,
        "metrics": {
            "reproducibility_confidence_score_rcs": rcs,
            "pipeline_determinism_grade": determinism_grade,
            "data_volatility_index_dvi": dvi
        },
        "insights": insights
    }
    
    # Write report
    eval_dir = repo_path / "evaluation"
    eval_dir.mkdir(exist_ok=True)
    report_file = eval_dir / f"{vid[:8]}_evaluation_metrics.json"
    report_file.write_text(json.dumps(report, indent=2), encoding='utf-8')
    
    return report, report_file
