#!/usr/bin/env python3
"""
Unquenched lattice-QCD HMC scaffold for DFD-QCD Boundary Program I.

This file is deliberately a scaffold rather than a fake production run.
It defines the exact steps needed for Nf=2 or 2+1 dynamical Wilson/clover/staggered
fermion execution. Implementing this physically requires a sparse Dirac operator,
CG/BiCGStab solvers, even-odd preconditioning, RHMC for odd flavors, long Markov
chains, autocorrelation analysis, and scale setting.

Use this as the bridge from the DFD frozen-input ledger to a production codebase
such as openQCD, Chroma, Grid, QUDA, MILC, or CPS.
"""
from __future__ import annotations
from dataclasses import dataclass, asdict
import json
from pathlib import Path

@dataclass(frozen=True)
class DFDUnquenchedRunSpec:
    gauge_group: str = "SU(3)"
    gauge_action: str = "Wilson plaquette or Symanzik-improved"
    fermion_action: str = "Wilson-clover initially; staggered/domain-wall optional for production"
    flavors: str = "2+1 light/strange; charm optional later"
    theta_qcd: float = 0.0
    alpha_s_MZ: float = 0.1187
    target_observables: tuple = (
        "m_pi", "f_pi", "m_K", "m_rho", "m_N", "string_tension", "topological_susceptibility"
    )
    required_steps: tuple = (
        "choose lattice spacings and volumes with m_pi L >= 4",
        "construct gauge links U_mu(x)",
        "define Dirac operator D[U,m_q] using DFD fixed quark masses",
        "sample pseudofermions phi with action phi^dagger (D^dagger D)^-1 phi",
        "draw conjugate momenta P in su(3)",
        "leapfrog/Omelyan molecular dynamics with reversible area-preserving integrator",
        "Metropolis accept/reject using full Hamiltonian",
        "measure two-point correlators and Wilson loops after thermalization",
        "estimate autocorrelation times and bin/jackknife errors",
        "perform continuum and infinite-volume extrapolation"
    )
    production_warning: str = (
        "This scaffold does not claim an executed unquenched ensemble. It is the exact bridge spec. "
        "A real run should be performed in a production lattice-QCD framework."
    )


def write_spec(out: str = "results/unquenched_hmc_run_spec.json") -> None:
    path = Path(out)
    path.parent.mkdir(parents=True, exist_ok=True)
    spec = DFDUnquenchedRunSpec()
    data = asdict(spec)
    data["target_observables"] = list(data["target_observables"])
    data["required_steps"] = list(data["required_steps"])
    with path.open("w") as f:
        json.dump(data, f, indent=2)
    print(json.dumps(data, indent=2))

if __name__ == "__main__":
    write_spec()
