from __future__ import annotations

import json
from pathlib import Path


def markdown(source: str) -> dict:
    return {
        "cell_type": "markdown",
        "metadata": {},
        "source": [line + "\n" for line in source.strip().splitlines()],
    }


def code(source: str) -> dict:
    return {
        "cell_type": "code",
        "execution_count": None,
        "metadata": {},
        "outputs": [],
        "source": [line + "\n" for line in source.strip().splitlines()],
    }


cells = [
    markdown(
        """
# PolicyFaultBench — التجربة النهائية الآمنة

هذا الدفتر يشغّل **Claude Sonnet 5** و **Gemini 3.6 Flash** على:

- 40 حالة اصطناعية فقط.
- 10 تكرارات لكل حالة.
- 400 تشغيل لكل نموذج.
- ترتيب عشوائي ثابت وقابل لإعادة الإنتاج.
- حفظ مباشر في Google Drive واستئناف تلقائي بعد الانقطاع.

لا يستهدف الدفتر أي منصة أو جهاز أو حساب حقيقي، ولا يطبع مفاتيح API.

## قبل التشغيل

1. تأكد من تفعيل السرّين `ANTHROPIC_API_KEY` و`GEMINI_API_KEY` لهذا الدفتر.
2. اضغط **Run all**.
3. ارفع ملف `PolicyFaultBench_v0.3.0_DEFINITIVE.zip` عندما يُطلب.
4. وافق على ربط Google Drive لحفظ نقاط الاستئناف.

قد يستغرق التشغيل الكامل قرابة ساعتين أو أكثر بسبب حد Gemini المجاني.
"""
    ),
    code(
        """
from google.colab import drive, files, userdata
from pathlib import Path
import hashlib, json, os, shutil, subprocess, sys, time, zipfile

drive.mount('/content/drive')
drive_root = Path('/content/drive/MyDrive/PolicyFaultBench_Definitive_v1')
drive_root.mkdir(parents=True, exist_ok=True)

uploaded = files.upload()
archives = [name for name in uploaded if name.endswith('.zip') and 'DEFINITIVE' in name]
assert len(archives) == 1, 'ارفع حزمة DEFINITIVE واحدة فقط'

work = Path('/content/pfb_definitive_work')
if work.exists():
    shutil.rmtree(work)
work.mkdir(parents=True)
with zipfile.ZipFile(archives[0]) as archive:
    for item in archive.infolist():
        target = (work / item.filename).resolve()
        assert work.resolve() in target.parents or target == work.resolve(), 'مسار ZIP غير آمن'
    archive.extractall(work)

root = work / 'PolicyFaultBench'
assert (root / 'pyproject.toml').is_file(), 'بنية الحزمة غير صحيحة'
print({'project_loaded': True, 'drive_checkpoint': str(drive_root)})
"""
    ),
    code(
        """
required = ('ANTHROPIC_API_KEY', 'GEMINI_API_KEY')
env = os.environ.copy()
for name in required:
    value = userdata.get(name)
    assert value and len(value) >= 20, f'السر {name} غير متاح لهذا الدفتر'
    env[name] = value
env['PFB_LIVE_ENABLED'] = 'true'
env['PFB_STUDY_ENABLED'] = 'true'
env['PYTHONPATH'] = str(root / 'src')

config_path = root / 'config' / 'experiment.json'
config = json.loads(config_path.read_text())
config['live_enabled'] = True
config['study_enabled'] = True
config['models']['anthropic'] = 'claude-sonnet-5'
config['models']['gemini'] = 'gemini-3.6-flash'
config_path.write_text(json.dumps(config, indent=2) + '\\n')

manifest = json.loads((root / 'manifests' / 'owned_assets.json').read_text())
assert manifest['synthetic_only'] is True
assert manifest['public_egress'] is False
assert config['definitive_study']['repetitions'] == 10
assert config['definitive_study']['planned_trials_per_provider'] == 400
print({'gates_ready': True, 'keys_present': list(required), 'keys_printed': False})
"""
    ),
    code(
        """
checks = [
    [sys.executable, '-m', 'unittest', 'discover', '-s', str(root/'tests'), '-q'],
    [sys.executable, '-m', 'policyfaultbench.cli', '--root', str(root), 'validate'],
    [sys.executable, '-m', 'policyfaultbench.cli', '--root', str(root), 'study-plan',
     '--output-dir', str(drive_root)],
]
for command in checks:
    result = subprocess.run(command, env=env, text=True, capture_output=True)
    print(result.stdout)
    if result.returncode:
        print(result.stderr)
        raise RuntimeError('فشل التحقق قبل التشغيل')
print('نجح التحقق الكامل قبل أي اتصال مدفوع.')
"""
    ),
    code(
        """
def run_provider(provider, delay, max_cycles=12):
    status_path = drive_root / f'study_status_{provider}.json'
    for cycle in range(1, max_cycles + 1):
        command = [
            sys.executable, '-m', 'policyfaultbench.cli', '--root', str(root),
            'study-run', provider, '--output-dir', str(drive_root),
            '--delay-seconds', str(delay),
        ]
        result = subprocess.run(command, env=env, text=True, capture_output=True)
        print(result.stdout)
        if result.stderr:
            print(result.stderr[-1000:])
        assert status_path.is_file(), f'لم يُنشأ ملف حالة {provider}'
        status = json.loads(status_path.read_text())
        print({
            'provider': provider,
            'cycle': cycle,
            'complete': status['primary_complete'],
            'remaining': status['remaining'],
            'cost_usd': status['completed_cost_usd'],
            'stop_reason': status['stop_reason'],
        })
        if status['invocation_containment_failures']:
            raise RuntimeError('تم إيقاف الدراسة فورًا بسبب فشل احتواء')
        if status['remaining'] == 0:
            return status
        reason = status.get('stop_reason', '')
        if reason.startswith('transient_abort:'):
            wait_seconds = 90 if provider == 'gemini' else 45
            print(f'انتظار {wait_seconds} ثانية ثم الاستئناف من آخر نقطة...')
            time.sleep(wait_seconds)
            continue
        raise RuntimeError(f'توقف غير عابر في {provider}: {reason}')
    raise RuntimeError(f'تجاوز {provider} عدد دورات الاستئناف المسموح')

anthropic_status = run_provider('anthropic', 0.0)
gemini_status = run_provider('gemini', 15.5)
print({'anthropic_complete': anthropic_status['remaining'] == 0,
       'gemini_complete': gemini_status['remaining'] == 0})
"""
    ),
    code(
        """
config = json.loads(config_path.read_text())
config['live_enabled'] = False
config['study_enabled'] = False
config_path.write_text(json.dumps(config, indent=2) + '\\n')

result_manifest = {
    'schema_version': '1.0',
    'study': 'pfb-definitive-v1',
    'providers': {
        'anthropic': anthropic_status,
        'gemini': gemini_status,
    },
    'files': {},
}
for path in sorted(drive_root.glob('*')):
    if path.is_file():
        result_manifest['files'][path.name] = {
            'bytes': path.stat().st_size,
            'sha256': hashlib.sha256(path.read_bytes()).hexdigest(),
        }
(drive_root / 'claude_gemini_result_manifest.json').write_text(
    json.dumps(result_manifest, indent=2, sort_keys=True) + '\\n'
)

archive_base = '/content/PolicyFaultBench_DEFINITIVE_CLAUDE_GEMINI_results'
archive_path = shutil.make_archive(archive_base, 'zip', drive_root)
print({'result_archive': archive_path, 'live_gates_relocked': True})
files.download(archive_path)
"""
    ),
    markdown(
        """
## بعد اكتمال التشغيل

سيُنزل ملف:

`PolicyFaultBench_DEFINITIVE_CLAUDE_GEMINI_results.zip`

أرسل هذا الملف فقط. إذا انقطع Colab، افتح الدفتر مجددًا وشغّله؛ سيقرأ النتائج
من Google Drive ويتابع الحالات المتبقية دون إعادة الحالات المكتملة.
"""
    ),
]

notebook = {
    "cells": cells,
    "metadata": {
        "colab": {
            "name": "PolicyFaultBench_Colab_DEFINITIVE.ipynb",
            "provenance": [],
        },
        "kernelspec": {
            "display_name": "Python 3",
            "language": "python",
            "name": "python3",
        },
        "language_info": {"name": "python"},
    },
    "nbformat": 4,
    "nbformat_minor": 5,
}

output = Path(__file__).resolve().parents[2] / "PolicyFaultBench_Colab_DEFINITIVE.ipynb"
output.write_text(json.dumps(notebook, indent=2, ensure_ascii=False) + "\n")
print(output)
