"""
PLUMLOOM ENGINE - Batch Progression Generator
Genera secuencias de progresión NSFW (7 pasos) para múltiples personajes.
Uso: python Engine/batch_progression.py [--chars N] [--dry-run]
"""
import requests
import base64
import random
import time
import re
import os
import sys
from pathlib import Path
from datetime import datetime

BASE_DIR = Path(__file__).parent.parent
FORGE_URL = "http://127.0.0.1:7860"
OUTPUT_DIR = BASE_DIR / "Output" / "batch_progression"
WILDCARD_DIR = BASE_DIR / "Archivos" / "progression_wildcards"
CHAR_FILE = BASE_DIR / "Archivos" / "personajes.txt"

MASTER = (
    "masterpiece, best quality, absurdres, highres, score_9, score_8_up, "
    "1girl, solo, "
    "<lora:IFL_v1.0_IL:0.7> <lora:add-detail-xl:0.5> "
    "<lora:blackwhiplash(bwl)-guy90-Illust-Lorav3:0.6> blaash, "
    "<lora:scara2b_ill_v1.00:0.7> scara2b-style, "
    "<lora:Add_color_ILXLv1:3>,"
)

NEG = (
    "lowres, bad anatomy, bad hands, error, missing fingers, extra digit, "
    "fewer digits, cropped, worst quality, low quality, normal quality, "
    "jpeg artifacts, signature, watermark, username, blurry, artist name, "
    "bad feet, multiple views, splits, 2girls, extra people, "
    "duplicate_character, cloned_character, ugly, deformed, disfigured, "
    "mutation, mutated, extra_limbs, fused_fingers, long_neck, cross-eyed, "
    "censored, mosaic censoring, bar censor, "
    "mirror, reflection, mirrored, glass_reflection, reflective_surface"
)

STEP_NAMES = [
    "01_outfit",
    "02_undress",
    "03_underwear",
    "04_presenting",
    "05_sexual",
    "06_explicit",
    "07_climax",
]

STEP_LABELS = [
    "OUTFIT",
    "UNDRESS",
    "UNDERWEAR",
    "PRESENTING",
    "SEXUAL",
    "EXPLICIT",
    "CLIMAX",
]


def load_wildcards():
    wildcards = {}
    for filename in ["step1_outfit.txt", "step2_undress.txt", "step3_underwear.txt",
                     "step4_presenting.txt", "step5_sexual.txt", "step6_explicit.txt",
                     "step7_climax.txt", "cameras.txt", "scenes.txt"]:
        filepath = WILDCARD_DIR / filename
        if filepath.exists():
            with open(filepath, "r", encoding="utf-8") as f:
                lines = [l.strip() for l in f if l.strip() and not l.startswith("#")]
            key = filename.replace(".txt", "")
            wildcards[key] = lines
    return wildcards


def load_characters(count=None):
    with open(CHAR_FILE, "r", encoding="utf-8") as f:
        lines = [l.strip() for l in f if l.strip()]
    if count:
        return random.sample(lines, min(count, len(lines)))
    return lines


def extract_char_name(char_line):
    match = re.search(r">([^,]+)", char_line)
    if match:
        raw = match.group(1).strip()
        return re.sub(r"[^a-zA-Z0-9]", "_", raw)[:20]
    return "unknown"


def build_prompt(char_line, step_wildcard, camera, scene):
    return f"{MASTER} {char_line}, age up, {step_wildcard}, {camera}, {scene}"


def generate_image(prompt, outpath):
    payload = {
        "prompt": prompt,
        "negative_prompt": NEG,
        "width": 832,
        "height": 1216,
        "steps": 28,
        "cfg_scale": 5,
        "sampler_name": "DPM++ 2M Karras",
        "batch_size": 1,
        "n_iter": 1,
        "seed": -1,
        "clip_skip": 2,
    }

    try:
        resp = requests.post(f"{FORGE_URL}/sdapi/v1/txt2img", json=payload, timeout=300)
        if resp.status_code == 200:
            img = base64.b64decode(resp.json()["images"][0])
            with open(outpath, "wb") as f:
                f.write(img)
            return True, len(img) // 1024
        return False, resp.status_code
    except Exception as e:
        return False, str(e)


def run_batch(char_count=3, dry_run=False):
    wildcards = load_wildcards()
    characters = load_characters(char_count)

    OUTPUT_DIR.mkdir(parents=True, exist_ok=True)

    print("=" * 55)
    print(f"  PROGRESSION BATCH - {len(characters)} characters x 7 steps")
    print("=" * 55)

    total = len(characters) * 7
    done = 0

    for ci, char_line in enumerate(characters):
        char_name = extract_char_name(char_line)
        scene = random.choice(wildcards.get("scenes.txt", ["bedroom, soft lighting, evening"]))

        print(f"\n--- {char_name} (scene: {scene}) ---")

        for si in range(7):
            step_key = f"step{si+1}_{['outfit','undress','underwear','presenting','sexual','explicit','climax'][si]}"
            wc_list = wildcards.get(step_key, [""])
            step_wildcard = random.choice(wc_list)

            camera = random.choice(wildcards.get("cameras.txt", ["cowboy shot"]))
            prompt = build_prompt(char_line, step_wildcard, camera, scene)

            filename = f"{char_name}_{STEP_NAMES[si]}.png"
            outpath = OUTPUT_DIR / filename

            done += 1
            print(f"  [{done}/{total}] {STEP_LABELS[si]}: {step_wildcard[:50]}...")

            if dry_run:
                print(f"    [DRY-RUN] Would generate: {filename}")
                print(f"    Prompt: {prompt[:100]}...")
            else:
                ok, result = generate_image(prompt, outpath)
                if ok:
                    print(f"    [OK] {result}KB")
                else:
                    print(f"    [FAIL] {result}")

                time.sleep(2)

    print("\n" + "=" * 55)
    print(f"  COMPLETADO - {done} images in {OUTPUT_DIR}")
    print("=" * 55)


if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description="Progression Batch Generator")
    parser.add_argument("--chars", type=int, default=3, help="Number of characters")
    parser.add_argument("--dry-run", action="store_true", help="Print prompts without generating")
    args = parser.parse_args()

    run_batch(char_count=args.chars, dry_run=args.dry_run)
