"""Readback checks for numberdb.org/T626; run with Sage after filling the draft.

Pass a permitted NumberDB API key on stdin to read this private draft.
This checks the stored intervals, not merely recomputation by the generator.
"""
import json
import sys
import os
import numberdb.sage as numberdb
from numberdb._generate import _stored_entries
from sage.rings.rational_field import QQ
import mpmath as mp
import generate as g
from checks import key, written_bounds, quadrature


def mpq(q):
    return mp.mpf(str(q.numerator()))/mp.mpf(str(q.denominator()))


def main():
    key_text=sys.stdin.read().strip()
    if '=' in key_text and key_text.split('=',1)[0].replace('_','').isalnum():
        key_text=key_text.split('=',1)[1].strip().strip('\"\'')
    numberdb.configure(api_key=key_text)
    document=numberdb.table('T626')
    stored=_stored_entries(document)
    params=list(g.Resistance().enumerate())
    assert list(stored)==[key(p) for p in params]
    bounds={k:written_bounds(s) for k,s in stored.items()}
    mp.mp.dps=145
    exact_known={'triangular,A,1,0':QQ(1)/3,'honeycomb,B,0,0':QQ(2)/3,'honeycomb,A,1,0':QQ(1)}
    max_ulps=mp.mpf(0)
    for p in params:
        name=key(p)
        lo,hi=bounds[name]
        q=quadrature(p,130)
        assert mp.isfinite(q)
        if name in exact_known:
            assert lo==hi==exact_known[name]
            assert abs(q-mpq(lo))<mp.mpf('1e-120')
        else:
            assert lo<hi and (hi-lo)<QQ(1)/10**97
            assert mpq(lo)<q<mpq(hi),(name,'stored interval excludes independent integral')
            mid=(lo+hi)/2
            max_ulps=max(max_ulps,abs(q-mpq(mid))/mpq((hi-lo)/2))
    def t(m,n):
        if (m,n)==(0,0): return QQ(0),QQ(0)
        a,b=g.canonical(m,n)
        return bounds.get('triangular,A,%d,%d'%(a,b))
    def h(s,m,n):
        if s=='A':
            if (m,n)==(0,0): return QQ(0),QQ(0)
            a,b=g.canonical(m,n)
        else: a,b=max(g.b_orbit(m,n))
        return bounds.get('honeycomb,%s,%d,%d'%(s,a,b))
    def relation(terms):
        lo=QQ(0); hi=QQ(0)
        for c,interval in terms:
            assert interval is not None
            a,b=interval
            lo+=c*(a if c>=0 else b)
            hi+=c*(b if c>=0 else a)
        assert lo<=0<=hi and hi-lo<QQ(1)/10**96,(str(lo),str(hi))
    reductions=0
    harmonic={'triangular':0,'honeycomb':0}
    for p in params:
        m,n=int(p['m']),int(p['n'])
        s=p['sublattice']
        if p['lattice']=='honeycomb':
            helpers=[t(m,n)] if s=='A' else [t(m,n),t(m+1,n),t(m+1,n+1)]
            relation([(1,h(s,m,n))]+[(-3 if s=='A' else -1,v) for v in helpers])
            reductions+=1
            neighbors=[h('B',m,n),h('B',m-1,n),h('B',m-1,n-1)] if s=='A' else [h('A',m,n),h('A',m+1,n),h('A',m+1,n+1)]
            center=h(s,m,n); degree=3
        else:
            neighbors=[t(m+a,n+b) for a,b in g.STEPS]
            center=t(m,n); degree=6
        if all(v is not None for v in neighbors):
            relation([(degree,center)]+[(-1,v) for v in neighbors])
            harmonic[p['lattice']]+=1
    report=g.Resistance().verify(sample=None)
    assert report.ok
    print(json.dumps({'table':'T626','generator_verify':str(report),'ordered_entries':len(stored),
       'independent_integrals_on_stored_values':84,'quadrature_working_digits':130,
       'maximum_midpoint_error_in_last_place_units':mp.nstr(max_ulps,12),
       'exact_rational_rows_checked':3,'honeycomb_reductions_using_stored_values':reductions,
       'harmonic_stencils_entirely_inside_stored_range':harmonic,
       'boundary_note':'Outer stencils require unstored neighbors and are checked exactly in checks.py.',
       'skill_manifest':'agents/runs/20261030T125612Z-build-skills/manifest.json'},indent=2))


if __name__=='__main__': main()
