"""
generuj-wan3.py - klip z Wan 3.0 przez API OpenRouter, z dźwiękiem, także z obrazu startowego (promptowy.com/wan-ai/)
Autor: Piotr Olszewski, promptowy.com. Licencja skryptu: MIT. Sprawdzone 26.09.2026 (OpenRouter, alibaba/wan-3.0).

Potrzebujesz: klucza OpenRouter w zmiennej środowiskowej OPENROUTER_API_KEY i biblioteki requests (pip install requests).
Koszt: cennik OpenRouter podaje 0,05 / 0,10 / 0,20 USD za sekundę (480p / 720p / 1080p), a faktycznie naliczył mi
0,085 USD za sekundę w 720p (5 s = 0,425 USD) i 0,2125 USD za klip 2 s w 480p - czyli minimum jak za 5 sekund.
Skrypt przed wysłaniem pokazuje szacunek i pyta o zgodę.

Przykłady (PowerShell: najpierw  $env:OPENROUTER_API_KEY = "sk-or-..." ):
  python generuj-wan3.py "a yellow tram passing a rainy street at dusk, static camera"
  python generuj-wan3.py "mist drifts over the lake, static camera" --obraz jezioro.png --sekundy 8
  python generuj-wan3.py "szkic ujęcia" --rozdzielczosc 480p --sekundy 3 --tak     (tani podgląd, bez pytania)
"""
import argparse, base64, json, mimetypes, os, sys, time

try:
    import requests
except ImportError:
    sys.exit("Brak biblioteki requests. Zainstaluj: pip install requests")

MODEL = "alibaba/wan-3.0"
CENA = {"480p": 0.0425, "720p": 0.085, "1080p": 0.17}   # USD za sekundę faktycznie naliczane przez OpenRouter 26.09.2026
MIN_SEKUND = 5   # w moim teście klip 2 s kosztował tyle co 5 s


def main():
    a = argparse.ArgumentParser(description="Klip z Wan 3.0 przez OpenRouter")
    a.add_argument("polecenie", help="opis ujęcia; dialog po polsku wpisz w cudzysłowie w treści polecenia")
    a.add_argument("--obraz", help="obraz startowy (pierwsza klatka): plik PNG/JPG albo adres https")
    a.add_argument("--sekundy", type=int, default=5, choices=range(2, 31), metavar="2-30")
    a.add_argument("--rozdzielczosc", default="720p", choices=list(CENA))
    a.add_argument("--proporcje", default="16:9", choices=["16:9", "4:3", "1:1", "3:4", "9:16"])
    a.add_argument("--bez-dzwieku", action="store_true")
    a.add_argument("--seed", type=int)
    a.add_argument("--tak", action="store_true", help="nie pytaj o zgodę na koszt")
    a.add_argument("--wyjscie", default="wan3")
    x = a.parse_args()
    klucz = os.environ.get("OPENROUTER_API_KEY")
    if not klucz:
        sys.exit("Ustaw klucz: $env:OPENROUTER_API_KEY = \"sk-or-...\" (PowerShell) albo set OPENROUTER_API_KEY=... (cmd)")
    szac = CENA[x.rozdzielczosc] * max(x.sekundy, MIN_SEKUND)
    print(f"Wan 3.0: {x.sekundy} s, {x.rozdzielczosc}, {x.proporcje}, dźwięk: {'nie' if x.bez_dzwieku else 'tak'}. Szacowany koszt: {szac:.2f} USD")
    if not x.tak and input("Wysłać? [t/N] ").strip().lower() not in ("t", "tak", "y"):
        sys.exit("Anulowano.")
    body = {"model": MODEL, "prompt": x.polecenie, "duration": x.sekundy, "resolution": x.rozdzielczosc,
            "aspect_ratio": x.proporcje, "generate_audio": not x.bez_dzwieku}
    if x.seed is not None:
        body["seed"] = x.seed
    if x.obraz:
        if x.obraz.startswith("https://"):
            url = x.obraz
        else:
            typ = mimetypes.guess_type(x.obraz)[0] or "image/png"
            url = f"data:{typ};base64," + base64.b64encode(open(x.obraz, "rb").read()).decode()
        body["frame_images"] = [{"type": "image_url", "image_url": {"url": url}, "frame_type": "first_frame"}]
    H = {"Authorization": "Bearer " + klucz, "Content-Type": "application/json"}
    t0 = time.time()
    r = requests.post("https://openrouter.ai/api/v1/videos", headers=H, json=body, timeout=120)
    if r.status_code >= 300:
        sys.exit(f"OpenRouter odrzucił zadanie ({r.status_code}): {r.text[:500]}")
    zad = r.json()
    url = zad.get("polling_url") or f"https://openrouter.ai/api/v1/videos/{zad['id']}"
    print(f"Zadanie {zad.get('id')} przyjęte. Generowanie trwa zwykle 2-4 minuty...")
    while True:
        time.sleep(15)
        s = requests.get(url, headers=H, timeout=60).json()
        st = s.get("status")
        print(f"\r  {st}, {time.time() - t0:.0f} s", end="", flush=True)
        if st == "completed":
            break
        if st in ("failed", "cancelled", "expired"):
            print(); sys.exit("Nie udało się: " + json.dumps(s, ensure_ascii=False)[:600])
    print()
    os.makedirs(x.wyjscie, exist_ok=True)
    plik = os.path.join(x.wyjscie, f"wan3_{time.strftime('%Y%m%d_%H%M%S')}.mp4")
    v = requests.get(s["unsigned_urls"][0], headers=H, timeout=300)
    open(plik, "wb").write(v.content)
    koszt = (s.get("usage") or {}).get("cost")
    print(f"Gotowe: {plik} ({len(v.content) / 1e6:.1f} MB), {time.time() - t0:.0f} s, koszt: {koszt} USD")


if __name__ == "__main__":
    main()
