#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""Login ulang Playwright ke RSIA Kendangsari (fresh state) lalu touch-save
beberapa post dengan menekan tombol Save/Update. Diadaptasi dari
das_pw_touch_save_multi.py untuk domain + password + PIDs RSIA.

HANYA touch-save (tekan tombol Save/Update), TIDAK mengubah konten/tanggal/status.
Hasil dicatat ke /tmp/rsia_touch_save_result.json
"""
import sys, json, time
from playwright.sync_api import sync_playwright

USER = "bambangbot"
LOGIN_PW = "C00l_man&314554"  # password login biasa akun (bukan app password)
BASE = "https://rsia.kendangsari.com"
STATE = "/tmp/rsiak_state.json"
RESULT_FILE = "/tmp/rsia_touch_save_result.json"
MAX_GOTO = 90      # detik per goto (commit)
MAX_LOGIN = 150    # detik max login
RETRIES = 3

results = {}

def record(pid, status, note=""):
    results[pid] = {"status": status, "note": note}
    print(f"PID {pid} -> {status}")

def save_result():
    with open(RESULT_FILE, "w") as f:
        json.dump(results, f, indent=2)

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

def ensure_login(ctx, pg):
    goto_light(pg, f"{BASE}/wp-admin/", MAX_GOTO)
    for _ in range(30):
        if "wp-login" not in pg.url and "wp-admin" in pg.url:
            return True
        if pg.locator("#user_login").count() > 0:
            break
        pg.wait_for_timeout(3000)
    if pg.locator("#user_login").count() > 0:
        goto_light(pg, f"{BASE}/wp-login.php", MAX_GOTO)
        for _ in range(30):
            if pg.locator("#user_login").count() > 0:
                break
            pg.wait_for_timeout(3000)
        pg.fill("#user_login", USER)
        pg.fill("#user_pass", LOGIN_PW)
        pg.click("#wp-submit", no_wait_after=True)
        for _ in range(50):  # max 150s
            pg.wait_for_timeout(3000)
            if "wp-login" not in pg.url and "wp-admin" in pg.url:
                ctx.storage_state(path=STATE)
                print("LOGIN_OK, state saved")
                return True
            if pg.locator("#login_error").count() > 0:
                print("LOGIN_ERROR:", pg.locator("#login_error").inner_text(timeout=2000)[:150])
                return False
        print("LOGIN_TIMEOUT url:", pg.url)
        return False
    return False

PAPER = [
    "#publish",                                        # Classic Editor utama (input#publish, value=Update)
    "button.editor-post-publish-button__button",        # Gutenberg modern (paling andal)
    "button.editor-post-publish-button",                # fallback selector lama
    "div.editor-post-publish-button button",            # container-based
]


def btn_text(el):
    """Baca label tombol: utk input pakai value attr, utk button mungkin inner_text."""
    try:
        tagname = el.evaluate("el => el.tagName").lower()
        if tagname == "input":
            v = el.get_attribute("value")
            return (v or "").strip()[:40]
        return (el.inner_text(timeout=2000) or "").strip()[:40]
    except Exception:
        return ""


def find_button(pg, timeout_s):
    """Temukan tombol Publish/Update yang VISIBLE. Return (locator, kind)."""
    import time as _t
    deadline = _t.time() + timeout_s
    while _t.time() < deadline:
        for sel in PAPER:
            try:
                for el in pg.locator(sel).all():
                    try:
                        if el.is_visible():
                            return el, sel
                    except Exception:
                        continue
            except Exception:
                continue
        pg.wait_for_timeout(2000)
    return None, None


def touch_save(pg, pid, idx, total):
    url = f"{BASE}/wp-admin/post.php?post={pid}&action=edit"
    goto_light(pg, url, MAX_GOTO)
    btn, sel = find_button(pg, MAX_GOTO)  # sampai ~90s cari tombol visible
    if btn is None:
        record(pid, "NO_BUTTON", f"url={pg.url[:70]}")
        print(f"[{idx}/{total}] PID {pid}: NO_BUTTON (url={pg.url[:70]})")
        save_result()
        return False
    text = btn_text(btn)
    try:
        btn.click(no_wait_after=True)
    except Exception as e:
        print(f"  click err: {str(e)[:60]}")
        try:
            btn.click(force=True, no_wait_after=True)  # force fallback
        except Exception as e2:
            record(pid, "FAILED_AFTER_CLICK", f"click err {str(e2)[:50]}")
            save_result()
            return False
    print(f"[{idx}/{total}] PID {pid}: CLICKED ({sel} '{text}')")
    # tunggu state saved / tombol kembali jadi 'Update'
    saved = False
    for _ in range(20):
        pg.wait_for_timeout(3000)
        st = pg.locator(".editor-post-saved-state").first
        if st.count():
            try:
                t = st.inner_text(timeout=2000).strip()
            except Exception:
                t = ""
            if t:
                print(f"    -> saved state: {t[:40]}")
                saved = True
                break
        # Classic editor: #publish value kembalih ke 'Update' setelah berubah 'Publishing…'
        cur, csel = find_button(pg, 2)
        if cur is not None and csel == "#publish":
            try:
                v = cur.get_attribute("value") or ""
            except Exception:
                v = ""
            if "Update" in v:
                saved = True
                break
        # Gutenberg: tombol kembali jadi 'Update'
        if cur is not None and csel != "#publish":
            t2 = btn_text(cur)
            if "Update" in t2:
                saved = True
                break
    if saved:
        record(pid, "SAVED", f"sel={sel} btn_text={text}")
    else:
        record(pid, "FAILED_AFTER_CLICK", "no saved-state observed")
    save_result()
    return saved

def main():
    pids = [4354, 4351, 4348, 4345, 4342, 4339, 4335]
    # allow override via argv: PID,PID,...
    if len(sys.argv) > 1 and sys.argv[1].strip():
        cands = [int(x) for x in sys.argv[1].split(",") if x.strip()]
        if cands:
            pids = cands
    with sync_playwright() as p:
        b = p.chromium.launch(headless=True, args=["--no-sandbox", "--disable-dev-shm-usage"])
        ctx = b.new_context(user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
        pg = ctx.new_page()
        if not ensure_login(ctx, pg):
            print("ABORT: login gagal")
            b.close()
            save_result()
            return 1
        for i, pid in enumerate(pids, 1):
            ok = False
            for attempt in range(1, RETRIES + 1):
                print(f"--- [{i}/{len(pids)}] PID {pid} attempt {attempt}/{RETRIES} ---")
                ok = touch_save(pg, pid, i, len(pids))
                if ok:
                    break
                if results.get(pid, {}).get("status") == "NO_BUTTON":
                    # login mungkin terlepas; coba pastikan login dulu
                    if not ensure_login(ctx, pg):
                        print("  re-login gagal")
                        break
                time.sleep(3)
            if not ok and results.get(pid, {}).get("status") not in ("SAVED",):
                record(pid, "FAILED", "after retries")
        b.close()
    save_result()
    print("ALL_DONE")
    return 0

sys.exit(main())
