import sys, json, collections, hashlib
sys.path.insert(0,'/tmp/claude-1000')
import gen
R, bk = gen.R, gen.bk
S='/tmp/claude-1000/stage/'
sp = open(S+'spells_us.orig.txt','rb').read()
db = open(S+'dbstr_us.orig.txt','rb').read()
assert hashlib.md5(sp).hexdigest()=='042eb514b17e40c9740e9e5a662e496a' and hashlib.md5(db).hexdigest()=='32bcb9081273f124f1fb35bc7e842114'
spl = sp.split(b'\n'); dbl = db.split(b'\n')
assert spl[-1]!=b'' and dbl[-1]!=b''  # originals have no trailing newline; keep that
sidx = {int(l.split(b'^',1)[0]):i for i,l in enumerate(spl)}
# existing dbstr type 6
d6 = {}; used6=set()
for i,l in enumerate(dbl):
    p = l.split(b'^',3)
    if p[1]==b'6':
        assert int(p[0]) not in d6; d6[int(p[0])] = i
cnt = collections.Counter(d['descnum'] for d in R.values() if d['descnum']!='0')
spell_desc_all = set(int(k) for k in cnt)
sym = sorted([d for d in R.values() if d['name'].startswith('Sympathetic') and gen.info(d)[0]], key=lambda d:int(d['id']))
nxt = 112001
newdesc = {}        # spell id -> new descnum
text = {}           # spell id -> text
for d in sym:
    sid=int(d['id']); t = gen.describe(d)
    assert '%' not in t and '^' not in t and '\n' not in t and all(ord(c)<128 for c in t)
    text[sid]=t
    if cnt[d['descnum']]>1:
        while nxt in d6 or nxt in spell_desc_all: nxt+=1
        newdesc[sid]=nxt; nxt+=1
print('spells',len(sym),'new descnum',len(newdesc),'range',min(newdesc.values()),max(newdesc.values()))
# spells_us edits
changed_spell=set(); minlvl_changes=0; desc_changes=0
for sid in bk:
    f = spl[sidx[sid]].split(b'^')
    assert f[0]==str(sid).encode()
    assert int(f[23])==bk[sid] and f[89]==b'142', (sid,f[23],f[89])
    assert int(R[sid]['effect_base_value4'])==1
    f[23]=b'1'; spl[sidx[sid]]=b'^'.join(f); changed_spell.add(sid); minlvl_changes+=1
for sid,nd in newdesc.items():
    f = spl[sidx[sid]].split(b'^')
    assert f[155]==R[sid]['descnum'].encode()
    f[155]=str(nd).encode(); spl[sidx[sid]]=b'^'.join(f); changed_spell.add(sid); desc_changes+=1
# dbstr edits
rep=0; app=[]
for sid,t in text.items():
    if sid in newdesc:
        app.append((newdesc[sid], t))
    else:
        dn=int(R[sid]['descnum'])
        line=f"{dn}^6^{t}^0".encode()
        if dn in d6: dbl[d6[dn]]=line; rep+=1
        else: app.append((dn,t))
for dn,t in sorted(app): dbl.append(f"{dn}^6^{t}^0".encode())
open(S+'spells_us.txt','wb').write(b'\n'.join(spl))
open(S+'dbstr_us.txt','wb').write(b'\n'.join(dbl))
# verify
o=sp.split(b'\n'); n=open(S+'spells_us.txt','rb').read().split(b'\n')
assert len(o)==len(n); dif=[i for i in range(len(o)) if o[i]!=n[i]]
assert len(dif)==len(changed_spell), (len(dif),len(changed_spell))
for i in dif:
    a=o[i].split(b'^'); b=n[i].split(b'^'); assert len(a)==len(b)
    assert all(a[k]==b[k] for k in range(len(a)) if k not in (23,155))
o=db.split(b'\n'); n=open(S+'dbstr_us.txt','rb').read().split(b'\n')
assert True
dd=[i for i in range(len(o)) if o[i]!=n[i]]
assert len(dd)==rep and len(n)-len(o)==len(app)
assert all(o[i].split(b'^')[:2]==n[i].split(b'^')[:2] and o[i].split(b'^')[1]==b'6' for i in dd)
assert b'%' not in b''.join(n[len(o):]) and all(b'%' not in n[i] for i in dd)
json.dump({'sympathetic_spells_described':len(sym),'by_family':{'spa339':sum(1 for d in sym if gen.info(d)[0][0]==339),'spa383':sum(1 for d in sym if gen.info(d)[0][0]==383)},
 'spells_us_rows_changed':len(dif),'spa142_min_level_rows':minlvl_changes,'descnum_rows_changed':desc_changes,
 'dbstr_lines_replaced':rep,'dbstr_lines_appended':len(app),'new_descnum_range':[min(newdesc.values()),max(newdesc.values())],
 'not_described_no_proc':[489,26007,26008,26009],'min_level_still_70':[24408,39614]},open(S+'diff_summary.json','w'),indent=1)
# artifacts
with open(S+'samples.txt','w') as f:
    for d in sym:
        sid=int(d['id']); f.write(f"{sid}\t{d['name']}\tdescnum {newdesc.get(sid,d['descnum'])}\t{text[sid]}\n")
with open(S+'descnum_map.tsv','w') as f:
    for sid,nd in newdesc.items(): f.write(f"{sid}\t{R[sid]['descnum']}\t{nd}\n")
print(open(S+'diff_summary.json').read())
