#!/usr/bin/env python3
import json
import urllib.parse
import urllib.request
import time
from pathlib import Path

PUBLIC_URL = "https://disk.yandex.ru/d/NjkmlkTUnYawKA"
API = "https://cloud-api.yandex.net/v1/disk/public/resources"
OUT = Path("/home/spazio/ksd30_transcription/downloads")
OUT.mkdir(parents=True, exist_ok=True)

params = urllib.parse.urlencode({"public_key": PUBLIC_URL, "limit": 1000})
with urllib.request.urlopen(f"{API}?{params}", timeout=60) as response:
    listing = json.load(response)

items = listing.get("_embedded", {}).get("items", [])
audio = [item for item in items if item.get("type") == "file" and item.get("name", "").lower().endswith(".mp3")]
manifest = []
for index, item in enumerate(audio, 1):
    name = item["name"]
    target = OUT / name
    expected = int(item.get("size") or 0)
    if target.exists() and target.stat().st_size == expected:
        print(f"SKIP {index}/{len(audio)} {name} ({expected} bytes)", flush=True)
    else:
        query = urllib.parse.urlencode({"public_key": PUBLIC_URL, "path": item["path"]})
        with urllib.request.urlopen(f"{API}/download?{query}", timeout=60) as response:
            href = json.load(response)["href"]
        temp = target.with_suffix(target.suffix + ".part")
        for attempt in range(1, 6):
            try:
                print(f"DOWNLOAD {index}/{len(audio)} attempt={attempt} {name} ({expected} bytes)", flush=True)
                with urllib.request.urlopen(href, timeout=900) as source, temp.open("wb") as destination:
                    while True:
                        chunk = source.read(1024 * 1024)
                        if not chunk:
                            break
                        destination.write(chunk)
                if expected and temp.stat().st_size != expected:
                    raise RuntimeError(f"Size mismatch for {name}: {temp.stat().st_size} != {expected}")
                temp.replace(target)
                break
            except Exception as exc:
                temp.unlink(missing_ok=True)
                if attempt == 5:
                    raise
                print(f"RETRY {name}: {type(exc).__name__}: {exc}", flush=True)
                time.sleep(attempt * 3)
    manifest.append({"name": name, "path": item["path"], "bytes": expected, "local": str(target)})

manifest_path = Path("/home/spazio/ksd30_transcription/manifest.json")
manifest_path.write_text(json.dumps({"folder": listing.get("name"), "count": len(manifest), "files": manifest}, ensure_ascii=False, indent=2), encoding="utf-8")
print(f"DONE files={len(manifest)} manifest={manifest_path}", flush=True)
