#!/usr/bin/env python3
"""
Etsy SVG Generation Pipeline
Generates images via DALL-E, converts to SVG, prepares for review.
"""

import os
import sys
import json
import time
import random
import hashlib
import subprocess
from datetime import datetime
from pathlib import Path
from openai import OpenAI

# Paths
WORKSPACE = Path.home() / ".openclaw/workspace"
ETSY_DIR = WORKSPACE / "etsy"
PROMPTS_DIR = ETSY_DIR / "prompts"
PENDING_DIR = ETSY_DIR / "pending-review"
ASSETS_DIR = WORKSPACE / "assets"
THEMES_FILE = PROMPTS_DIR / "themes.json"
HISTORY_FILE = PROMPTS_DIR / "prompt-history.json"
USER_IDEAS_FILE = PROMPTS_DIR / "user-ideas.json"
REVIEW_DATA_FILE = ETSY_DIR / "review-data.json"

# Config
RATE_LIMIT_DELAY = 15  # seconds between API calls
IMAGE_SIZE = "1024x1024"
IMAGE_QUALITY = "standard"

def load_json(path, default=None):
    """Load JSON file or return default."""
    if path.exists():
        with open(path) as f:
            return json.load(f)
    return default if default is not None else {}

def save_json(path, data):
    """Save data to JSON file."""
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(path, 'w') as f:
        json.dump(data, f, indent=2)

def get_prompt_hash(prompt):
    """Generate hash of prompt for duplicate detection."""
    return hashlib.md5(prompt.lower().encode()).hexdigest()[:12]

def load_prompt_history():
    """Load used prompts to avoid duplicates."""
    history = load_json(HISTORY_FILE, {"prompts": []})
    return set(h["hash"] for h in history.get("prompts", []))

def save_prompt_to_history(prompt, filename):
    """Save prompt to history."""
    history = load_json(HISTORY_FILE, {"prompts": []})
    history["prompts"].append({
        "hash": get_prompt_hash(prompt),
        "prompt": prompt,
        "filename": filename,
        "timestamp": datetime.now().isoformat()
    })
    save_json(HISTORY_FILE, history)

def generate_prompt(themes_data, used_hashes):
    """Generate a unique prompt from themes."""
    themes = themes_data["themes"]
    modifiers = themes_data["styleModifiers"]
    
    # Try up to 20 times to find unique prompt
    for _ in range(20):
        theme = random.choice(themes)
        subject = random.choice(theme["subjects"])
        modifier = random.choice(modifiers)
        
        prompt = f"{subject}, {modifier}, black silhouette on pure white background, no text, no watermark"
        
        if get_prompt_hash(prompt) not in used_hashes:
            return prompt, theme["name"], subject
    
    # Fallback: add random element
    prompt = f"{subject} variation {random.randint(1,999)}, {modifier}, black silhouette on pure white background"
    return prompt, theme["name"], subject

def check_user_ideas():
    """Check for user-submitted ideas."""
    ideas = load_json(USER_IDEAS_FILE, {"ideas": []})
    pending = [i for i in ideas.get("ideas", []) if not i.get("used")]
    return pending

def generate_image(client, prompt, output_path):
    """Generate image via DALL-E API."""
    try:
        response = client.images.generate(
            model="dall-e-3",
            prompt=prompt,
            size=IMAGE_SIZE,
            quality=IMAGE_QUALITY,
            n=1
        )
        
        image_url = response.data[0].url
        revised_prompt = response.data[0].revised_prompt
        
        # Download image
        import urllib.request
        urllib.request.urlretrieve(image_url, output_path)
        
        return True, revised_prompt
    except Exception as e:
        return False, str(e)

def convert_to_svg(png_path, svg_path):
    """Convert PNG to SVG using potrace."""
    try:
        # First convert to PBM (potrace input format)
        pbm_path = png_path.with_suffix('.pbm')
        
        # Use ImageMagick to convert to high-contrast black/white PBM
        subprocess.run([
            'convert', str(png_path),
            '-colorspace', 'gray',
            '-threshold', '50%',
            '-negate',
            str(pbm_path)
        ], check=True, capture_output=True)
        
        # Use potrace to convert to SVG
        subprocess.run([
            'potrace',
            '-s',  # SVG output
            '-o', str(svg_path),
            '--flat',  # No grouping
            '-t', '10',  # Suppress speckles
            str(pbm_path)
        ], check=True, capture_output=True)
        
        # Clean up PBM
        pbm_path.unlink()
        
        return True
    except Exception as e:
        print(f"  SVG conversion error: {e}")
        return False

def simplify_svg(svg_path):
    """Simplify SVG paths using Inkscape."""
    try:
        # Use Inkscape to simplify
        subprocess.run([
            'inkscape',
            '--actions=select-all;path-simplify;export-filename:{};export-do'.format(svg_path),
            str(svg_path)
        ], check=True, capture_output=True, timeout=30)
        return True
    except Exception as e:
        print(f"  Simplify warning (non-fatal): {e}")
        return True  # Non-fatal, continue anyway

def add_watermark(png_path, output_path):
    """Add watermark to preview image."""
    watermark = ASSETS_DIR / "watermark.png"
    if not watermark.exists():
        # No watermark file, just copy
        subprocess.run(['cp', str(png_path), str(output_path)])
        return
    
    try:
        subprocess.run([
            'convert', str(png_path),
            str(watermark),
            '-gravity', 'center',
            '-composite',
            str(output_path)
        ], check=True, capture_output=True)
    except Exception as e:
        print(f"  Watermark error: {e}")
        subprocess.run(['cp', str(png_path), str(output_path)])

def generate_formats(base_name, svg_path, output_dir):
    """Generate all format variants (PNG, PDF, DXF)."""
    formats_created = []
    
    # PNG (transparent, from SVG)
    png_path = output_dir / f"{base_name}.png"
    try:
        subprocess.run([
            'inkscape',
            str(svg_path),
            '--export-type=png',
            f'--export-filename={png_path}',
            '--export-width=3000'
        ], check=True, capture_output=True, timeout=30)
        formats_created.append('png')
    except Exception as e:
        print(f"  PNG export error: {e}")
    
    # PDF
    pdf_path = output_dir / f"{base_name}.pdf"
    try:
        subprocess.run([
            'inkscape',
            str(svg_path),
            '--export-type=pdf',
            f'--export-filename={pdf_path}'
        ], check=True, capture_output=True, timeout=30)
        formats_created.append('pdf')
    except Exception as e:
        print(f"  PDF export error: {e}")
    
    # DXF
    dxf_path = output_dir / f"{base_name}.dxf"
    try:
        subprocess.run([
            'inkscape',
            str(svg_path),
            '--export-type=dxf',
            f'--export-filename={dxf_path}'
        ], check=True, capture_output=True, timeout=30)
        formats_created.append('dxf')
    except Exception as e:
        print(f"  DXF export error: {e}")
    
    return formats_created

def main(num_images=25):
    """Main generation pipeline."""
    print(f"=== Etsy SVG Generation Pipeline ===")
    print(f"Generating {num_images} images...")
    print(f"Start time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print()
    
    # Initialize OpenAI client
    # Get API key from OpenClaw config
    config_path = Path.home() / ".openclaw/openclaw.json"
    with open(config_path) as f:
        config = json.load(f)
    
    api_key = config.get("models", {}).get("providers", {}).get("openai", {}).get("apiKey")
    if not api_key:
        print("ERROR: OpenAI API key not found in config")
        sys.exit(1)
    
    client = OpenAI(api_key=api_key)
    
    # Load data
    themes = load_json(THEMES_FILE)
    if not themes:
        print("ERROR: themes.json not found")
        sys.exit(1)
    
    used_hashes = load_prompt_history()
    user_ideas = check_user_ideas()
    
    # Prepare output
    PENDING_DIR.mkdir(parents=True, exist_ok=True)
    
    results = []
    successful = 0
    failed = 0
    
    for i in range(num_images):
        print(f"[{i+1}/{num_images}] ", end="")
        
        # Check user ideas first
        if user_ideas:
            idea = user_ideas.pop(0)
            prompt = idea["text"] + ", minimalist silhouette, clean lines suitable for vinyl cutting, black silhouette on pure white background"
            theme_name = "User Idea"
            subject = idea["text"]
            # Mark idea as used
            ideas_data = load_json(USER_IDEAS_FILE, {"ideas": []})
            for item in ideas_data["ideas"]:
                if item.get("text") == idea["text"]:
                    item["used"] = True
            save_json(USER_IDEAS_FILE, ideas_data)
        else:
            prompt, theme_name, subject = generate_prompt(themes, used_hashes)
        
        # Generate filename
        timestamp = datetime.now().strftime("%Y%m%d-%H%M%S")
        safe_subject = "".join(c if c.isalnum() else "-" for c in subject.lower())[:30]
        base_name = f"{safe_subject}-{timestamp}"
        
        print(f"{theme_name}: {subject[:40]}...")
        
        # Generate image
        png_path = PENDING_DIR / f"{base_name}-original.png"
        success, result = generate_image(client, prompt, png_path)
        
        if not success:
            print(f"  ❌ Generation failed: {result}")
            failed += 1
            time.sleep(RATE_LIMIT_DELAY)
            continue
        
        print(f"  ✓ Image generated")
        
        # Convert to SVG
        svg_path = PENDING_DIR / f"{base_name}.svg"
        if convert_to_svg(png_path, svg_path):
            print(f"  ✓ Converted to SVG")
            simplify_svg(svg_path)
        else:
            print(f"  ⚠ SVG conversion failed, keeping PNG only")
        
        # Create watermarked preview
        preview_path = PENDING_DIR / f"{base_name}-preview.png"
        add_watermark(png_path, preview_path)
        print(f"  ✓ Preview created")
        
        # Save to history
        save_prompt_to_history(prompt, base_name)
        used_hashes.add(get_prompt_hash(prompt))
        
        # Track result
        results.append({
            "id": base_name,
            "theme": theme_name,
            "subject": subject,
            "prompt": prompt,
            "revised_prompt": result,
            "timestamp": datetime.now().isoformat(),
            "files": {
                "original": str(png_path.name),
                "svg": str(svg_path.name) if svg_path.exists() else None,
                "preview": str(preview_path.name)
            },
            "status": "pending"
        })
        
        successful += 1
        
        # Rate limit delay (except after last image)
        if i < num_images - 1:
            print(f"  ⏳ Waiting {RATE_LIMIT_DELAY}s...")
            time.sleep(RATE_LIMIT_DELAY)
    
    # Save review data
    review_data = load_json(REVIEW_DATA_FILE, {"images": []})
    review_data["images"].extend(results)
    review_data["lastGeneration"] = datetime.now().isoformat()
    save_json(REVIEW_DATA_FILE, review_data)
    
    print()
    print(f"=== Complete ===")
    print(f"Successful: {successful}")
    print(f"Failed: {failed}")
    print(f"End time: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
    print(f"Images ready for review in: {PENDING_DIR}")

if __name__ == "__main__":
    num = int(sys.argv[1]) if len(sys.argv) > 1 else 25
    main(num)

# TONY-APPROVED: 2026-03-01 | sha:b342a044
