"""How to perform a basic, single program calculation using BigChem"""

from qcio import CalcType, ProgramInput, Structure
from qcop import exceptions

from bigchem import compute

# Create the structure
# Can also open a structure from a file
# structure = Structure.open("path/to/h2o.xyz")
structure = Structure(
    symbols=["O", "H", "H"],
    geometry=[  # type: ignore
        [0.0, 0.0, 0.0],
        [0.52421003, 1.68733646, 0.48074633],
        [1.14668581, -0.45032174, -1.35474466],
    ],
)

# Define the program input
prog_input = ProgramInput(
    structure=structure,
    calctype=CalcType.energy,  # May also use "energy", "gradient", "hessian"
    model={"method": "b3lyp", "basis": "6-31g"},  # type: ignore
    keywords={},  # Optional: Additional keywords to pass to the QC program
)

# Submit computation to BigChem. Collect all files produced by the program
future_output = compute.delay("terachem", prog_input, collect_files=True)

# Check status (optional)
print(f"Calculation Status: {future_output.status}")

try:
    # Get result from BigChem
    prog_output = future_output.get()
except exceptions.QCOPBaseError as e:
    assert e.program_output is not None  # For mypy
    prog_output = e.program_output  # ProgramFailure object
    prog_output.traceback  # Full traceback of the error
    prog_output.stdout  # Stdout from the program
    prog_output.input_data  # Input data used to generate the calculation
    prog_output.provenance  # Provenance of generated calculation
    # Do something with the error
    raise e  # Or re-raise the error if desired

# Remove result from backend
future_output.forget()

### Accessing results ###
# Stdout from the program
print(prog_output.stdout)  # or output.pstdout for short
# Input data used to generate the calculation
print(prog_output.input_data)
# Provenance of generated calculation
print(prog_output.provenance)
# Files generated by the program
print(prog_output.files.keys())

if prog_output.success:
    # Check results
    print("Energy:", prog_output.results.energy)

else:
    print(prog_output.traceback)
    print("Calculation failed")

# Optionally write all files to disk for inspection
# output.save_files("where/to/save/files")
