import csv,json,subprocess,tempfile
from collections import Counter
csv.field_size_limit(100_000_000)
from pathlib import Path
from urllib.parse import urlsplit
p=Path(__file__).resolve().parent

def rows(name):
    with (p/name).open() as f:return list(csv.DictReader(f))
ids=[r['element_id'] for r in rows('chr19.matrix.csv')]
for n in ['chr19.ccre.matrix.csv','chr19.ccre_metadata.csv','chr19.clinvar.matrix.csv','chr19.clinvar.metadata.csv']:
    assert [r['element_id'] for r in rows(n)]==ids
assert all(e.startswith('chr19:') for e in ids)
vs=rows('chr19.clinvar.variants.csv');links=rows('chr19.clinvar.links.csv')
with tempfile.TemporaryDirectory() as t:
    t=Path(t)
    (t/'e.bed').write_text(''.join(e.replace(':','\t').replace('-','\t')+'\t'+e+'\n' for e in ids))
    (t/'v.bed').write_text(''.join('{chrom}\t{start}\t{end}\t{variant_key}\n'.format(**v) for v in vs))
    out=subprocess.run(['bedtools','intersect','-a',str(t/'e.bed'),'-b',str(t/'v.bed'),'-wa','-wb'],capture_output=True,text=True,check=True)
    actual={(r[3],r[7]) for line in out.stdout.splitlines() if (r:=line.split('\t'))}
assert actual=={(r['element_id'],r['variant_key']) for r in links}
counts=Counter(a for a,b in actual)
assert all(int(r['ClinVar overlap count'])==counts[r['element_id']] for r in rows('chr19.clinvar.matrix.csv'))
cs=json.loads((p/'chr19.clinvar.obsSets.json').read_text())['tree'][0]['children']
assert {r[0] for r in cs[0]['set']}=={e for e in ids if counts[e]}
assert {r[0] for r in cs[1]['set']}=={e for e in ids if not counts[e]}
c=json.loads((p/'chr19.json').read_text())
assert 'ENCFF960GTR' in c['name'] and '775WBY' not in json.dumps(c)
for d in c['datasets']:
    for f in d['files']:
        assert f['url'].startswith('https://users.abdenlab.org/voy/vitessce_cvh/hepg2_sci/chr19/')
        assert (p/Path(urlsplit(f['url']).path).name).is_file()
for v in c['layout']:
    for key,scope in v['coordinationScopes'].items():
        for s in scope if isinstance(scope,list) else [scope]:assert s in c['coordinationSpace'][key]
expected_labels = {'classes': ['ccre_matches', 'ccre_count'], 'clinvar': ['clinvar_count'], 'A': ['ccre_count', 'clinvar_count']}
for v in c['layout']:
    if v['component'] == 'heatmap':
        assert v['coordinationScopes']['obsLabelsType'] == expected_labels[v['coordinationScopes']['featureType']]
assert [v['props']['observationsLabelOverride'] for v in c['layout'] if v['component']=='heatmap']==['Regulatory element','\u00a0','\u00a0']
report=json.loads((p/'clinvar.validation.json').read_text())
report.update(bedtools_overlap_crosscheck=True,row_alignment_verified=True,config_references_valid=True,counts_and_groups_verified=True)
(p/'clinvar.validation.json').write_text(json.dumps(report,indent=2)+'\n')
print('PASS: matrix row alignment, independent ClinVar intersections/counts/groups, config dependencies/scopes, axis titles.')
