from common import *
import sqlite3,json,hashlib,ast
g,t=load();checks=[]
def check(name,value):
    checks.append({'check':name,'passed':bool(value)})
    if not value:raise AssertionError(name)
source=sqlite3.connect(f'file:{R.parent}/2026-09-05/catalog.sqlite?mode=ro',uri=True)
check('raw game row count',source.execute('select count(*) from games where type=0').fetchone()[0]==len(g)==184664)
check('unique game IDs',g.appid.nunique()==len(g))
check('raw review sum',source.execute('select sum(reviews_filtered_count) from games where type=0').fetchone()[0]==g.reviews.sum())
check('raw released flags',source.execute('select count(*) from games where type=0 and is_coming_soon=0').fetchone()[0]==g.released.sum())
for row in g.sample(250,random_state=7007).itertuples():
    raw=source.execute('select data_json from games where appid=?',(row.appid,)).fetchone()[0];d=json.loads(raw)
    check('sample raw name '+str(row.appid),d.get('name')==row.name)
    check('sample raw review count '+str(row.appid),d.get('reviews',{}).get('summary_filtered',{}).get('review_count',0)==row.reviews)
check('tag identities valid',set(t.appid)<=set(g.appid))
check('tag ranks 1-20',t['rank'].between(1,20).all())
check('no duplicate game tags',not t.duplicated(['appid','tagid']).any())
for path in R.glob('*.csv'):
    d=pd.read_csv(path)
    if 'n' in d:
        for col in ['r50','r100','r556','r1000','joint','h50']:
            if col in d:check(path.name+' '+col+' within denominator',(d[col].dropna()>=0).all() and (d[col]<=d.n).all())
    for col in d:
        if col.endswith('_rate'):check(path.name+' '+col+' proportion',d[col].dropna().between(0,1).all())
        if col.endswith('_observed') and 'supported' in d:
            valid=d[col].notna()&d.supported.notna();check(path.name+' '+col+' supported denominator',(d.loc[valid,col]<=d.loc[valid,'supported']).all())
pool=g[g.valid&~g.free&~g.explicit&g.year.between(2023,2025)]
check('main pool with single date repair',len(pool)==38493)
table=pd.read_csv(R/'tags_and_pairs.csv')
for rank in [7,20]:
    for names in [['Card Game','Base Building'],['Roguelite','Mystery'],['Online Co-Op','Roguelite']]:
        sets=[set(t.loc[t.tag.eq(n)&t['rank'].le(rank),'appid']) for n in names];a=pool[pool.appid.isin(set.intersection(*sets))]
        z=table[table['rank'].eq(rank)&table.period.eq('2023-25')&table.group.eq(' + '.join(names))].iloc[0]
        check('recount '+str(rank)+' '+str(names),len(a)==z.n and int(a.reviews.ge(100).sum())==z.r100)
c=pd.read_parquet(R/'career_games.parquet')
for dev in c.dev.drop_duplicates().sample(100,random_state=7007):
    a=c[c.dev.eq(dev)].sort_values(['date','appid']);past=[]
    for row in a.itertuples():
        check('career prior '+str(row.appid),row.prior_best==max(past,default=0));past.append(row.reviews)
hist=pd.read_csv(R/'history_windows.csv');check('24 primary histories',len(hist)==24)
check('SNKRX exact 30day',hist.set_index('appid').loc[915310,'d30']==590)
check('BYTEPATH exact 30day',hist.set_index('appid').loc[760330,'d30']==71)
for a in hist.itertuples():check('monotonic history '+str(a.appid),a.d1<=a.d7<=a.d14<=a.d30<=a.d90 and (pd.isna(a.d365) or a.d90<=a.d365))
check('closed bulk network',json.loads((R.parent/'network_policy.json').read_text())['network_paused'])
check('no source image downloader',not (R.parent/'images.py').exists())
for p in R.glob('*.py'):ast.parse(p.read_text());check('syntax '+p.name,True)
(R/'validation.json').write_text(json.dumps({'checks':checks,'passed':len(checks),'failed':0},indent=2))
print('Passed',len(checks),'checks')
