#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""RSIA: BATCH upload semua webp ke Media Library via Playwright (satu navigasi).
set_input_files(list) -> WP upload semua -> lalu baca daftar attachment terbaru
dari upload.php utk memetakan file basename -> media id.
Input: /tmp/rsia_norm/to_upload.txt (paths).  Output: /tmp/rsia_norm/upload_id.json {basename:media_id}
"""
import os, sys, json, time
from playwright.sync_api import sync_playwright

BASE="https://rsia.kendangsari.com"
USER="bambangbot"; PW="C00l_man&314554"
STATE="/tmp/rsiak_state.json"
WORK="/tmp/rsia_norm"; os.makedirs(WORK,exist_ok=True)
LISTF=f"{WORK}/to_upload.txt"
OUTF=f"{WORK}/upload_id.json"
LOG=f"{WORK}/upload_batch_log.txt"

def log(*a):
    print(*a,flush=True)
    with open(LOG,'a') as f: f.write(" ".join(str(x) for x in a)+"\n")

def goto_light(pg,url,w=120):
    try: pg.goto(url,timeout=w*1000,wait_until="commit")
    except Exception as e: log("  goto warn",str(e)[:60])

def ensure_login(ctx,pg):
    goto_light(pg,f"{BASE}/wp-admin/",120)
    for _ in range(25):
        if "wp-login" not in pg.url and "wp-admin" in pg.url: log("LOGIN_OK"); return True
        if pg.locator("#user_login").count(): break
        pg.wait_for_timeout(2000)
    goto_light(pg,f"{BASE}/wp-login.php",120)
    for _ in range(25):
        if pg.locator("#user_login").count(): break
        pg.wait_for_timeout(2000)
    pg.fill("#user_login",USER); pg.fill("#user_pass",PW)
    pg.click("#wp-submit",no_wait_after=True)
    for _ in range(60):
        pg.wait_for_timeout(3000)
        if "wp-login" not in pg.url and "wp-admin" in pg.url:
            ctx.storage_state(path=STATE); log("LOGIN_OK(fresh)"); return True
        if pg.locator("#login_error").count(): log("LOGIN_ERR",pg.locator("#login_error").inner_text(timeout=2000)[:100]); return False
    log("LOGIN_TIMEOUT"); return False

def main():
    if not os.path.exists(LISTF):
        log("tidak ada to_upload.txt"); return 1
    files=[l.strip() for l in open(LISTF) if l.strip()]
    if not files:
        log("to_upload kosong"); return 1
    log("batch upload file:",len(files))
    # pecah jadi beberapa batch (hindari terlalu banyak sekaligus)
    BATCH=20
    with sync_playwright() as p:
        b=p.chromium.launch(headless=True,args=["--no-sandbox","--disable-dev-shm-usage"])
        ua="Mozilla/5.0 (Windows NT 10.0; Win64; x64) Chrome/120 Safari/537.36"
        ctx=b.new_context(storage_state=STATE if os.path.exists(STATE) else None,user_agent=ua)
        pg=ctx.new_page()
        if not ensure_login(ctx,pg): b.close(); return 1
        result={}
        if os.path.exists(OUTF): result=json.load(open(OUTF))
        # mapping basename
        def basename(path): return os.path.basename(path)
        for bi in range(0,len(files),BATCH):
            chunk=files[bi:bi+BATCH]
            log(f"\n-- batch {bi//BATCH+1} ({len(chunk)} file) --")
            goto_light(pg,f"{BASE}/wp-admin/media-new.php",120)
            inp=None
            for _ in range(40):
                pg.wait_for_timeout(3000)
                if pg.locator("input[type='file']").count():
                    inp=pg.locator("input[type='file']").first; break
                try:
                    if pg.locator("a:has-text('Upload Files')").count():
                        pg.locator("a:has-text('Upload Files')").first.click(no_wait_after=True)
                except Exception: pass
            if inp is None:
                for sel in ["#plupload-browse-button input[type=file]","input#async-upload"]:
                    if pg.locator(sel).count(): inp=pg.locator(sel).first; break
            if inp is None:
                log("  ! input file tak ada"); continue
            try:
                inp.set_input_files(chunk)
            except Exception as e:
                log("  ! set_input_files err",str(e)[:100]); continue
            log("  uploading %d files..."%len(chunk))
            # tunggu upload selesai: redirect upload.php + jumlah attachment >= bi+len
            for i in range(90):
                pg.wait_for_timeout(3000)
                if "upload.php" in pg.url:
                    try:
                        rows=pg.locator("#the-list tr")
                        n=rows.count()
                        # ambil media id + title
                        for k in range(n):
                            try:
                                row=rows.nth(k)
                                a=row.locator("a").first.get_attribute("href") or ""
                                title=row.locator(".title, .name").first.inner_text(timeout=1500).strip() if row.locator(".title, .name").first.count() else ""
                                if "post=" in a:
                                    mid=int(a.split("post=")[1].split("&")[0])
                                    # title biasanya = filename
                                    if title:
                                        result[title]=mid
                            except Exception: pass
                    except Exception: pass
                    # cukup tunggu beberapa periode
                    if i>=6: break
            log("  batch selesai, total mapped:",len(result))
            json.dump(result,open(OUTF,'w'),indent=1)
        b.close()
    # tampilkan mapping basename yg berhasil
    hits={}
    for f in files:
        bn=basename(f)
        if bn in result: hits[bn]=result[bn]
    log(f"\nuploaded mapped: {len(hits)}")
    # simpan map file->id utk semua yg ketemu
    json.dump(hits,open(WORK+"/upload_id.json",'w'),indent=1)

sys.exit(main())
