#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""instalar.py / atualizar.py — instala ou atualiza a skill `seed-ds` a partir de https://ds.seed.eng.br (só biblioteca padrão).
- Rodado de DENTRO de uma cópia instalada (…/seed-ds/scripts/atualizar.py): lê o VERSAO.json vivo; se a versão for a
  mesma, para; senão baixa o zip, confere o MD5 de CADA arquivo contra o VERSAO.json vivo, extrai ao lado e troca a
  pasta (a anterior vai para ../seed-ds.anterior, FORA da pasta de skills).
- Rodado de fora (baixado como instalar.py): instala em ~/.claude/skills/seed-ds (ou na pasta passada em --destino),
  com a mesma conferência de MD5. Serve para o Claude Code e para qualquer agente que leia skills de uma pasta.
Uso: python instalar.py [--destino <pasta que vai conter seed-ds/>] [--forcar]
Sai 0 = instalada/atualizada ou já em dia; 1 = MD5 divergente (nada trocado); 2 = sem rede."""
import hashlib, io, json, pathlib, shutil, sys, urllib.request, zipfile
BASE = 'https://ds.seed.eng.br'
args = sys.argv[1:]
meu = pathlib.Path(__file__).resolve()
dentro = (meu.parent.parent / 'VERSAO.json').is_file() and meu.parent.name == 'scripts'
if dentro:
    AQUI = meu.parent.parent
    local = json.loads((AQUI / 'VERSAO.json').read_text(encoding='utf-8'))
else:
    raiz = pathlib.Path(args[args.index('--destino') + 1]).expanduser().resolve() if '--destino' in args else pathlib.Path.home() / '.claude' / 'skills'
    AQUI = raiz / 'seed-ds'
    local = json.loads((AQUI / 'VERSAO.json').read_text(encoding='utf-8')) if (AQUI / 'VERSAO.json').is_file() else None
try:
    with urllib.request.urlopen(BASE + '/10-publicacao/skill/seed-ds/VERSAO.json', timeout=30) as r:
        vivo = json.loads(r.read().decode('utf-8'))
except Exception as e:
    print('sem rede ou VERSAO.json indisponível (%s) — nada trocado%s' % (e, '; instalada: ' + local['versao_skill'] if local else '')); sys.exit(2)
if local and vivo['versao_skill'] == local['versao_skill'] and '--forcar' not in args:
    print('skill seed-ds já em dia: %s (canon de %s) em %s' % (local['versao_skill'], local['data_do_ds'], AQUI)); sys.exit(0)
print(('versão instalada %s → publicada %s' % (local['versao_skill'], vivo['versao_skill'])) if local else ('instalando a versão %s em %s' % (vivo['versao_skill'], AQUI)), '(canon de %s); baixando o zip…' % vivo['data_do_ds'])
with urllib.request.urlopen(BASE + '/10-publicacao/skill/seed-ds.zip', timeout=120) as r:
    zbytes = r.read()
z = zipfile.ZipFile(io.BytesIO(zbytes))
decl = vivo['arquivos']
ruins = []
for n in z.namelist():
    k = n.split('/', 1)[1]
    if k == 'VERSAO.json':
        continue
    if k not in decl or decl[k]['md5'] != hashlib.md5(z.read(n)).hexdigest():
        ruins.append(k)
if ruins:
    print('MD5 divergente em %d arquivo(s) do zip — nada trocado: %s' % (len(ruins), ', '.join(ruins[:5]))); sys.exit(1)
novo = AQUI.parent / 'seed-ds.novo'
# a cópia anterior fica FORA da pasta de skills: qualquer pasta com SKILL.md dentro de ~/.claude/skills vira skill
anterior = AQUI.parent.parent / 'seed-ds.anterior'
if novo.exists(): shutil.rmtree(novo)
novo.mkdir(parents=True)
for n in z.namelist():
    dest = novo / n.split('/', 1)[1]
    dest.parent.mkdir(parents=True, exist_ok=True)
    dest.write_bytes(z.read(n))
if AQUI.exists():
    if anterior.exists(): shutil.rmtree(anterior)
    AQUI.rename(anterior)
novo.rename(AQUI)
print(('atualizada: %s → %s' % (local['versao_skill'], vivo['versao_skill'])) if local else ('instalada: %s' % vivo['versao_skill']), 'em %s%s' % (AQUI, ('; a versão anterior ficou em %s (pode apagar)' % anterior) if local else ''))
