#!/usr/bin/env python3
"""Upload all images to WordPress studiosoft.id via REST API."""

import base64
import json
import os
import time
import sys
import requests
from pathlib import Path

WORKDIR = "/home/mantapman/.hermes/profiles/atun/workspace"
WP_URL = "https://studiosoft.id/wp-json/wp/v2/media"
WP_USER = "bambangbot"
WP_PASS = "q26r RePo BVy6 pwU2 F3z7 ouyl"
MAP_PATH = os.path.join(WORKDIR, "wp_image_map.json")
BATCH_SIZE = 5
SAVE_INTERVAL = 10

# Auth header
auth_str = base64.b64encode(f"{WP_USER}:{WP_PASS}".encode()).decode()

# Load existing map
image_map = {}
if os.path.exists(MAP_PATH):
    try:
        with open(MAP_PATH) as f:
            data = json.load(f)
            # Normalise keys — remove leading ./ etc
            for k, v in data.items():
                norm = k.replace("./", "")
                image_map[norm] = v
        print(f"[INFO] Loaded existing map with {len(image_map)} entries")
    except Exception as e:
        print(f"[WARN] Could not load existing map: {e}")

upload_count = 0

def save_map():
    # Save with clean relative paths
    out = {}
    for k, v in image_map.items():
        if k.startswith(f"{WORKDIR}/"):
            rel = os.path.relpath(k, WORKDIR)
            out[rel] = v
        else:
            out[k] = v
    with open(MAP_PATH, "w") as f:
        json.dump(out, f, indent=2)
    global upload_count
    print(f"[SAVE] Map saved ({len(out)} entries, {upload_count} uploaded this session)")

def upload_file(filepath):
    """Upload a single file to WP. Returns (id, url) or (None, None) on failure."""
    relpath = os.path.relpath(filepath, WORKDIR)
    
    # Check if already uploaded (by relative path)
    if relpath in image_map:
        print(f"[SKIP] {relpath} — already uploaded")
        return image_map[relpath]["id"], image_map[relpath]["url"]
    
    # Check by absolute path too
    if filepath in image_map:
        print(f"[SKIP] {filepath} — already uploaded")
        return image_map[filepath]["id"], image_map[filepath]["url"]
    
    filename = os.path.basename(filepath)
    
    # Read file
    try:
        with open(filepath, "rb") as f:
            filedata = f.read()
    except Exception as e:
        print(f"[ERROR] Cannot read {relpath}: {e}")
        return None, None
    
    # Detect mime type from extension
    ext = filename.lower().rsplit(".", 1)[-1] if "." in filename else "png"
    mime_map = {"png": "image/png", "jpg": "image/jpeg", "jpeg": "image/jpeg", "webp": "image/webp", "gif": "image/gif"}
    mime = mime_map.get(ext, "image/png")
    
    headers = {
        "Authorization": f"Basic {auth_str}",
        "Content-Type": mime,
        "Content-Disposition": f"attachment; filename={filename}",
    }
    
    try:
        resp = requests.post(WP_URL, headers=headers, data=filedata, timeout=60)
        if resp.status_code in (200, 201):
            data = resp.json()
            img_id = data.get("id")
            img_url = data.get("source_url", "")
            if img_id:
                image_map[relpath] = {"id": img_id, "url": img_url}
                print(f"[OK] {relpath} → ID {img_id}")
                return img_id, img_url
        
        # If media already exists (code 500 / duplicate), try to find by slug
        if resp.status_code >= 400:
            print(f"[WARN] {relpath} — HTTP {resp.status_code}: {resp.text[:200]}")
            # Try slug-based lookup
            slug = Path(filename).stem.lower().replace(" ", "-").replace("_", "-").replace(".", "-")[:200]
            search_url = f"{WP_URL}?slug={slug}&per_page=1"
            try:
                sr = requests.get(search_url, headers={"Authorization": f"Basic {auth_str}"}, timeout=30)
                if sr.status_code == 200 and sr.json():
                    existing = sr.json()[0]
                    eid = existing.get("id")
                    eurl = existing.get("source_url", "")
                    image_map[relpath] = {"id": eid, "url": eurl}
                    print(f"[RECOVER] {relpath} → found existing ID {eid}")
                    return eid, eurl
            except Exception:
                pass
            
            return None, None
    except Exception as e:
        print(f"[ERROR] Upload {relpath} failed: {e}")
        return None, None

def get_files_from_folders():
    """Get all files ordered by priority."""
    all_files = []
    
    # 1. studiosoft_batch - sorted by date then filename
    batch_dir = os.path.join(WORKDIR, "studiosoft_batch")
    if os.path.isdir(batch_dir):
        dates = sorted(os.listdir(batch_dir))
        for date in dates:
            date_dir = os.path.join(batch_dir, date)
            if os.path.isdir(date_dir):
                files = sorted(os.listdir(date_dir))
                for f in files:
                    fp = os.path.join(date_dir, f)
                    if os.path.isfile(fp) and f.lower().endswith(('.png', '.jpg', '.jpeg', '.webp', '.gif')):
                        all_files.append(fp)
    
    # 2. uky_threads_images
    tidir = os.path.join(WORKDIR, "uky_threads_images")
    if os.path.isdir(tidir):
        files = sorted(os.listdir(tidir))
        for f in files:
            fp = os.path.join(tidir, f)
            if os.path.isfile(fp) and f.lower().endswith(('.png', '.jpg', '.jpeg', '.webp', '.gif')):
                all_files.append(fp)
    
    # 3. uky3_output - only *_biru.png variant
    uky3dir = os.path.join(WORKDIR, "uky3_output")
    if os.path.isdir(uky3dir):
        files = sorted(os.listdir(uky3dir))
        for f in files:
            if f.endswith("_biru.png"):
                fp = os.path.join(uky3dir, f)
                if os.path.isfile(fp):
                    all_files.append(fp)
    
    # 4. studiosoft_carousel
    cardir = os.path.join(WORKDIR, "studiosoft_carousel")
    if os.path.isdir(cardir):
        files = sorted(os.listdir(cardir))
        for f in files:
            fp = os.path.join(cardir, f)
            if os.path.isfile(fp) and f.lower().endswith(('.png', '.jpg', '.jpeg', '.webp', '.gif')):
                all_files.append(fp)
    
    return all_files

def main():
    global upload_count
    
    files = get_files_from_folders()
    total = len(files)
    print(f"[START] Found {total} files to process")
    
    # Count already uploaded
    skipped = 0
    remaining = []
    for fp in files:
        relpath = os.path.relpath(fp, WORKDIR)
        if relpath in image_map or fp in image_map:
            skipped += 1
        else:
            remaining.append(fp)
    
    print(f"[INFO] Already uploaded: {skipped}, Remaining: {len(remaining)}")
    
    if not remaining:
        print("[DONE] All files already uploaded!")
        save_map()
        return
    
    # Process in batches
    for i in range(0, len(remaining), BATCH_SIZE):
        batch = remaining[i:i+BATCH_SIZE]
        print(f"\n[BATCH {i//BATCH_SIZE + 1}/{(len(remaining)-1)//BATCH_SIZE + 1}]")
        
        for fp in batch:
            upload_file(fp)
            upload_count += 1
            time.sleep(1)  # 1 second delay between uploads
        
        # Save progress after each batch
        save_map()
        sys.stdout.flush()
    
    print(f"\n[DONE] Finished! Processed {upload_count} new uploads this session.")

if __name__ == "__main__":
    main()
