﻿def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--check', action='store_true')
    args = parser.parse_args()
    selected = json.loads((SOURCE / 'choice_v2.json').read_text(encoding='utf-8-sig'))['ok']
    assert len(selected) == len(set(selected)) == 54
    def order(f):
        m = re.fullmatch(r'B?(\d+)_([fe])_(.+)\.png', Path(f).name)
        assert m, f
        return m[2] == 'e', int(m[1]), f
    selected.sort(key=order)
    OUTPUT.mkdir(parents=True, exist_ok=True)
    rows = []
    for index, filename in enumerate(selected, 1):
        source = SOURCE / 'v2' / Path(filename).name
        if not source.exists():
            source = SOURCE / filename
        path = OUTPUT / f'{index:02}_{Path(filename).stem}.png'
        with Image.open(source) as original:
            im = original.convert('RGBA')
            if im.size != (512, 512):
                im.thumbnail((512, 512), Image.Resampling.LANCZOS)
                canvas = Image.new('RGBA', (512, 512))
                canvas.alpha_composite(im, ((512-im.width)//2, (512-im.height)//2))
                im = canvas
            im.save(path, optimize=True, compress_level=9)
            pixels = hashlib.sha256(im.tobytes()).hexdigest()
        assert path.stat().st_size <= 400000, filename
        rows.append(dict(source=filename, path=str(path), emoji=emoji(filename),
            sha256=hashlib.sha256(path.read_bytes()).hexdigest(), pixels=pixels))
    assert set(OUTPUT.glob('*.png')) == {Path(r['path']) for r in rows}
    print(f'Validated 54 PNG; max {max(Path(r["path"]).stat().st_size for r in rows)} bytes', flush=True)
    if args.check:
        return
    remote = request('getStickerSet', {'name': NAME}, allow_missing=True)
    mapping = json.loads(STATE.read_text(encoding='utf8')) if STATE.exists() else {}
    if remote:
        assert remote['sticker_type'] == 'regular'
        assert not any(s.get('is_animated') or s.get('is_video') for s in remote['stickers'])
        if not mapping:
            legacy = json.loads(LEGACY.read_text(encoding='utf8'))
            by_id = {s['file_id']: s for s in remote['stickers']}
            assert legacy['name'] == NAME and set(legacy['file_ids']) == set(by_id)
            assert len(legacy['rows']) == len(legacy['file_ids'])
            for row, file_id in zip(legacy['rows'], legacy['file_ids']):
                old_path = Path(row['path'])
                assert hashlib.sha256(old_path.read_bytes()).hexdigest() == row['sha256']
                with Image.open(old_path) as im:
                    pixels = hashlib.sha256(im.convert('RGBA').tobytes()).hexdigest()
                mapping[row['source']] = dict(sha256=row['sha256'], pixels=pixels,
                    file_unique_id=by_id[file_id]['file_unique_id'])
            save(mapping)
        assert {s['file_unique_id'] for s in remote['stickers']} <= {m['file_unique_id'] for m in mapping.values()}
    else:
        first = rows[:50]
        stickers = [dict(sticker=f'attach://f{i}', format='static', emoji_list=[r['emoji']]) for i,r in enumerate(first)]
        request('createNewStickerSet', dict(user_id=OWNER, name=NAME, title=TITLE,
            sticker_type='regular', stickers=json.dumps(stickers,ensure_ascii=False)),
            {f'f{i}':r['path'] for i,r in enumerate(first)})
        remote = request('getStickerSet', {'name':NAME})
        assert len(remote['stickers']) == 50
        mapping = {r['source']:dict(sha256=r['sha256'],pixels=r['pixels'],file_unique_id=s['file_unique_id']) for r,s in zip(first,remote['stickers'])}
        save(mapping)
    for index,row in enumerate(rows,1):
        saved = mapping.get(row['source'], {})
        existing = next((s for s in remote['stickers'] if s['file_unique_id'] == saved.get('file_unique_id')),None)
        if existing and (saved.get('sha256') == row['sha256'] or saved.get('pixels') == row['pixels']):
            saved.update(sha256=row['sha256'],pixels=row['pixels'])
            save(mapping)
            continue
        before = {s['file_unique_id'] for s in remote['stickers']}
        sticker = dict(sticker='attach://f0',format='static',emoji_list=[row['emoji']])
        fields = dict(user_id=OWNER,name=NAME,sticker=json.dumps(sticker,ensure_ascii=False))
        if existing:
            fields['old_sticker'] = existing['file_id']
        request('replaceStickerInSet' if existing else 'addStickerToSet',fields,{'f0':row['path']})
        remote = request('getStickerSet',{'name':NAME})
        added = [s for s in remote['stickers'] if s['file_unique_id'] not in before]
        assert len(added) == 1, 'Cannot identify uploaded sticker'
        mapping[row['source']] = dict(sha256=row['sha256'],pixels=row['pixels'],file_unique_id=added[0]['file_unique_id'])
        save(mapping)
        print(f'Updated {index}/54: {row["source"]}',flush=True)
    for source in list(mapping):
        if source in selected:
            continue
        existing = next((s for s in remote['stickers'] if s['file_unique_id'] == mapping[source]['file_unique_id']),None)
        if existing:
            request('deleteStickerFromSet',{'sticker':existing['file_id']})
        del mapping[source]
        save(mapping)
    remote = request('getStickerSet',{'name':NAME})
    current = remote['stickers']
    desired = [mapping[r['source']]['file_unique_id'] for r in rows]
    assert len(current) == 54 and {s['file_unique_id'] for s in current} == set(desired)
    for index,(identity,row) in enumerate(zip(desired,rows)):
        position = next(i for i,s in enumerate(current) if s['file_unique_id'] == identity)
        sticker = current[position]
        if position != index:
            request('setStickerPositionInSet',{'sticker':sticker['file_id'],'position':index})
            current.insert(index,current.pop(position))
        if sticker.get('emoji') != row['emoji']:
            request('setStickerEmojiList',{'sticker':sticker['file_id'],'emoji_list':json.dumps([row['emoji']],ensure_ascii=False)})
    if remote['title'] != TITLE:
        request('setStickerSetTitle',{'name':NAME,'title':TITLE})
    final = request('getStickerSet',{'name':NAME})
    assert final['title'] == TITLE and final['sticker_type'] == 'regular'
    assert [s['file_unique_id'] for s in final['stickers']] == desired
    assert [s.get('emoji') for s in final['stickers']] == [r['emoji'] for r in rows]
    assert all(not s.get('is_animated') and not s.get('is_video') and max(s['width'],s['height']) == 512 for s in final['stickers'])
    print('VERIFIED 54 regular/static, full-body then emotions; https://t.me/addstickers/'+NAME,flush=True)
