"""Regenerates the DRAT certificate for a stored fort-cover CNF whose proof-logging
re-solve did not complete (used for n = 22: the lazy loop proved UNSAT at bound 10
and stored the CNF and the fort list, but the process ended before the DRAT file
was written). Reads the stored DIMACS file verbatim (so its SHA-256 is unchanged),
re-solves it with CaDiCaL under proof logging, writes the DRAT proof, runs
drat-trim and appends the usual record to results/lower_bound_certificates.jsonl
and results/solver_runs.jsonl.

usage: python3 code/regen_fortcover_proof.py N BOUND
"""
import json
import os
import subprocess
import sys
import time

import common
from pysat.formula import CNF
from pysat.solvers import Solver

DRAT_TRIM = os.path.join(common.ROOT, "code", "tools", "drat-trim", "drat-trim")


def main(n, b):
    cert_dir = os.path.join(common.CERTS, "fortcover")
    cnf_path = os.path.join(cert_dir, "P%d_5_atmost%d.cnf" % (n, b))
    proof_path = os.path.join(cert_dir, "P%d_5_atmost%d.drat" % (n, b))
    forts_path = os.path.join(cert_dir, "P%d_5_atmost%d.forts.json" % (n, b))
    cnf = CNF(from_file=cnf_path)
    forts = json.load(open(forts_path))["forts"]
    t0 = time.time()
    with Solver(name="cadical195", bootstrap_with=cnf.clauses, with_proof=True) as s:
        sat = s.solve()
        proof = None if sat else s.get_proof()
    t_solve = time.time() - t0
    out = {"sat": sat, "solver": "cadical195", "solve_seconds": round(t_solve, 3),
           "cnf_path": os.path.relpath(cnf_path, common.ROOT), "cnf_sha256": common.sha256_file(cnf_path),
           "num_vars": cnf.nv, "num_clauses": len(cnf.clauses)}
    if sat:
        out["note"] = "stored CNF is satisfiable: no certificate"
    else:
        with open(proof_path, "w") as f:
            f.write("\n".join(proof) + "\n")
        out["proof_path"] = os.path.relpath(proof_path, common.ROOT)
        out["proof_sha256"] = common.sha256_file(proof_path)
        out["proof_lines"] = len(proof)
        t1 = time.time()
        cmd = [DRAT_TRIM, cnf_path, proof_path]
        r = subprocess.run(cmd, capture_output=True, text=True)
        out["checker_cmd"] = " ".join(os.path.relpath(c, common.ROOT) if c.startswith("/") else c for c in cmd)
        out["checker_exit"] = r.returncode
        out["checker_verified"] = ("s VERIFIED" in r.stdout)
        out["checker_seconds"] = round(time.time() - t1, 3)
        out["checker_stdout_tail"] = r.stdout.strip().splitlines()[-3:]
    out.update({"n": n, "k": 5, "bound": b, "method": "fort_cover_static_proof", "regenerated_from_stored_cnf": True,
                "forts_path": os.path.relpath(forts_path, common.ROOT), "forts_sha256": common.sha256_file(forts_path),
                "num_forts": len(forts), "utc": common.utcnow()})
    out.update(common.versions())
    common.append_jsonl(os.path.join(common.RESULTS, "solver_runs.jsonl"), out)
    if not sat:
        common.append_jsonl(os.path.join(common.RESULTS, "lower_bound_certificates.jsonl"), out)
    print(json.dumps(out))


if __name__ == "__main__":
    main(int(sys.argv[1]), int(sys.argv[2]))
