#!/usr/bin/env python3
"""Render Discord-style message capture to PNG.

Usage:
    python render-discord-capture.py --messages messages.json --output capture.png
    python render-discord-capture.py --messages-inline '[{"user":"kitt","body":"Test"}]' --output test.png

Requires: playwright (pip install playwright && playwright install chromium)
"""
import json
import argparse
import html
from pathlib import Path
from datetime import datetime

TEMPLATE_DIR = Path(__file__).parent.parent / "templates"
OUTPUT_DIR = Path(__file__).parent.parent / "social-captures"

# Agent role colors matching discord-message.html
ROLE_COLORS = {
    "assaf": "#2ecc71",
    "kitt": "#e67e22", 
    "julia": "#9b59b6",
    "ogilvy": "#e74c3c",
    "tatiana": "#1abc9c",
    "anton": "#5d6269",  # Darker grey for readability on white
    "anton ego": "#5d6269",  # Also handle full name
    "erica": "#f1c40f",
    "jessica": "#3498db",
    "dan": "#e91e63",
}

# Known bots
BOT_USERS = {"kitt", "julia", "ogilvy", "tatiana", "anton", "erica", "jessica", "dan"}


def escape_html(text: str) -> str:
    """Escape HTML but preserve intentional formatting."""
    text = html.escape(text)
    # Convert newlines to <br>
    text = text.replace("\n", "<br>")
    return text


def format_code_blocks(text: str) -> str:
    """Convert markdown code blocks to HTML."""
    import re
    # Multi-line code blocks
    text = re.sub(
        r'```(\w*)\n?(.*?)```',
        r'<div class="code-block">\2</div>',
        text,
        flags=re.DOTALL
    )
    # Inline code
    text = re.sub(r'`([^`]+)`', r'<code>\1</code>', text)
    return text


def file_to_data_url(file_path: str) -> str:
    """Convert file path to data URL."""
    import base64
    import mimetypes
    p = Path(file_path)
    if not p.exists():
        return None
    mime_type = mimetypes.guess_type(file_path)[0] or 'image/png'
    with open(p, 'rb') as f:
        b64 = base64.b64encode(f.read()).decode('utf-8')
    return f"data:{mime_type};base64,{b64}"


CE_LOGO_PATH = "/home/clawd/workspace/images/ce-logo-stacked.png"

def build_ce_template(messages_html: str, font_scale: float, avatar_size: int, avatar_font: int,
                      body_font: int, username_font: int, timestamp_font: int, 
                      bot_tag_font: int, code_font: int, result_image_path: str = None) -> str:
    """Build Curious Endeavor branded template."""
    logo_data_url = file_to_data_url(CE_LOGO_PATH) if Path(CE_LOGO_PATH).exists() else None
    logo_html = f'<img src="{logo_data_url}" alt="Curious Endeavor">' if logo_data_url else 'curious<br>endeavor.'
    
    # Result image on the right side
    if result_image_path:
        result_data_url = file_to_data_url(result_image_path)
        result_html = f'<div class="result-image"><img src="{result_data_url}" alt="Result"></div>' if result_data_url else ""
    else:
        result_html = ""
    
    return f'''<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    @import url('https://fonts.googleapis.com/css2?family=Playfair+Display:wght@400;500&display=swap');
    
    * {{
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }}
    
    html, body {{
      height: 675px;
    }}
    
    body {{
      font-family: 'gg sans', 'Noto Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
      background: #ffffff;
      padding: 30px;
      width: 1200px;
      display: flex;
      flex-direction: column;
      box-sizing: border-box;
    }}
    
    .logo {{
      margin-bottom: 20px;
      flex-shrink: 0;
    }}
    
    .logo img {{
      height: 60px;
      width: auto;
    }}
    
    .content-wrapper {{
      display: flex;
      gap: 24px;
      flex: 1;
    }}
    
    .messages-container {{
      background: #fafafa;
      border-radius: 10px;
      padding: 24px;
      min-height: calc(675px - 30px - 80px - 20px - 30px);  /* viewport - top padding - logo height - logo margin - bottom padding */
      flex: 1;
    }}
    
    .result-image {{
      flex-shrink: 0;
      display: flex;
      align-items: center;
    }}
    
    .result-image img {{
      max-height: 500px;
      max-width: 300px;
      border-radius: 10px;
      box-shadow: 0 4px 12px rgba(0,0,0,0.1);
    }}
    
    .messages {{
      display: flex;
      flex-direction: column;
      gap: 16px;
    }}
    
    .message {{
      display: flex;
      gap: 16px;
      padding: 4px 0;
    }}
    
    .avatar {{
      width: {avatar_size}px;
      height: {avatar_size}px;
      border-radius: 50%;
      flex-shrink: 0;
      background: #5865f2;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-weight: 600;
      font-size: {avatar_font}px;
    }}
    
    .avatar img {{
      width: 100%;
      height: 100%;
      border-radius: 50%;
      object-fit: cover;
    }}
    
    .content {{
      flex: 1;
    }}
    
    .header {{
      display: flex;
      align-items: baseline;
      gap: 8px;
      margin-bottom: 4px;
    }}
    
    .username {{
      font-weight: 600;
      font-size: {username_font}px;
    }}
    
    .bot-tag {{
      background: #5865f2;
      color: white;
      font-size: {bot_tag_font}px;
      font-weight: 600;
      padding: 2px 6px;
      border-radius: 3px;
      text-transform: uppercase;
    }}
    
    .timestamp {{
      color: #5c6470;
      font-size: {timestamp_font}px;
    }}
    
    .body {{
      color: #2e3338;
      font-size: {body_font}px;
      line-height: 1.4;
      white-space: pre-wrap;
    }}
    
    .body code {{
      background: #e8e8e8;
      padding: 2px 6px;
      border-radius: 4px;
      font-family: 'Consolas', 'Monaco', monospace;
      font-size: {code_font}px;
    }}
  </style>
</head>
<body>
  <div class="logo">{logo_html}</div>
  <div class="content-wrapper">
    <div class="messages-container">
      <div class="messages">
        {messages_html}
      </div>
    </div>
    {result_html}
  </div>
</body>
</html>'''


def render_message(msg: dict) -> str:
    """Render a single message to HTML."""
    user = msg.get("user", "Unknown")
    user_lower = user.lower()
    body = msg.get("body", "")
    timestamp = msg.get("timestamp", datetime.now().strftime("Today at %I:%M %p"))
    is_bot = msg.get("isBot", user_lower in BOT_USERS)
    avatar_url = msg.get("avatar")
    
    # Get role color
    color = ROLE_COLORS.get(user_lower, "#f2f3f5")
    role_class = user_lower if user_lower in ROLE_COLORS else ""
    
    # Avatar - image or initial
    if avatar_url:
        # Convert file paths to data URLs
        if avatar_url.startswith('/') or avatar_url.startswith('./'):
            data_url = file_to_data_url(avatar_url)
            if data_url:
                avatar_html = f'<img src="{data_url}" alt="{user}">'
            else:
                avatar_html = user[0].upper()
        else:
            avatar_html = f'<img src="{avatar_url}" alt="{user}">'
    else:
        avatar_html = user[0].upper()
    
    # Role/Bot tag
    role_title = msg.get("role")  # Custom role title like "Critic" or "Creative"
    if role_title:
        bot_tag = f'<span class="bot-tag">{role_title}</span>'
    elif is_bot:
        bot_tag = '<span class="bot-tag">Bot</span>'
    else:
        bot_tag = ""
    
    # Format body
    body_html = escape_html(body)
    body_html = format_code_blocks(body_html)
    
    return f'''
    <div class="message">
      <div class="avatar">{avatar_html}</div>
      <div class="content">
        <div class="header">
          <span class="username {role_class}" style="color:{color}">{user}</span>
          {bot_tag}
          <span class="timestamp">{timestamp}</span>
        </div>
        <div class="body">{body_html}</div>
      </div>
    </div>
    '''


def build_html(messages: list, theme: str = "dark", font_scale: float = 1.0, logo_path: str = None, template: str = "default", result_image: str = None) -> str:
    """Build complete HTML document from messages."""
    messages_html = "\n".join(render_message(m) for m in messages)
    
    # Logo at top
    if logo_path:
        logo_data_url = file_to_data_url(logo_path)
        logo_html = f'<div class="logo"><img src="{logo_data_url}" alt="Logo"></div>' if logo_data_url else ""
    else:
        logo_html = ""
    
    # Scaled font sizes
    body_font = int(16 * font_scale)
    username_font = int(16 * font_scale)
    timestamp_font = int(12 * font_scale)
    bot_tag_font = int(10 * font_scale)
    code_font = int(14 * font_scale)
    watermark_font = int(12 * font_scale)
    avatar_size = int(48 * font_scale)
    avatar_font = int(20 * font_scale)
    
    # CE branded template
    if template == "ce":
        return build_ce_template(messages_html, font_scale, avatar_size, avatar_font, body_font, 
                                  username_font, timestamp_font, bot_tag_font, code_font, result_image)
    
    # Theme colors
    if theme == "light":
        bg_color = "#ffffff"
        text_color = "#2e3338"
        timestamp_color = "#5c6470"
        code_bg = "#f2f3f5"
        watermark_color = "#b9bbbe"
    else:  # dark
        bg_color = "#313338"
        text_color = "#dbdee1"
        timestamp_color = "#949ba4"
        code_bg = "#2b2d31"
        watermark_color = "#4e5058"
    
    return f'''<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <style>
    * {{
      margin: 0;
      padding: 0;
      box-sizing: border-box;
    }}
    
    body {{
      font-family: 'gg sans', 'Noto Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
      background: {bg_color};
      padding: 24px;
      width: 1200px;
      min-height: 675px;
      display: flex;
      flex-direction: column;
    }}
    
    .messages {{
      flex: 1;
      display: flex;
      flex-direction: column;
      justify-content: center;
      gap: 16px;
    }}
    
    .message {{
      display: flex;
      gap: 16px;
      padding: 4px 0;
    }}
    
    .avatar {{
      width: {avatar_size}px;
      height: {avatar_size}px;
      border-radius: 50%;
      flex-shrink: 0;
      background: #5865f2;
      display: flex;
      align-items: center;
      justify-content: center;
      color: white;
      font-weight: 600;
      font-size: {avatar_font}px;
    }}
    
    .avatar img {{
      width: 100%;
      height: 100%;
      border-radius: 50%;
      object-fit: cover;
    }}
    
    .content {{
      flex: 1;
    }}
    
    .header {{
      display: flex;
      align-items: baseline;
      gap: 8px;
      margin-bottom: 4px;
    }}
    
    .username {{
      font-weight: 600;
      font-size: {username_font}px;
      color: #f2f3f5;
    }}
    
    .bot-tag {{
      background: #5865f2;
      color: white;
      font-size: {bot_tag_font}px;
      font-weight: 600;
      padding: 2px 6px;
      border-radius: 3px;
      text-transform: uppercase;
    }}
    
    .timestamp {{
      color: {timestamp_color};
      font-size: {timestamp_font}px;
    }}
    
    .body {{
      color: {text_color};
      font-size: {body_font}px;
      line-height: 1.4;
      white-space: pre-wrap;
    }}
    
    .body code {{
      background: {code_bg};
      padding: 2px 6px;
      border-radius: 4px;
      font-family: 'Consolas', 'Monaco', monospace;
      font-size: {code_font}px;
    }}
    
    .body .code-block {{
      background: {code_bg};
      padding: 12px;
      border-radius: 4px;
      margin: 8px 0;
      font-family: 'Consolas', 'Monaco', monospace;
      font-size: {code_font}px;
      overflow-x: auto;
      white-space: pre-wrap;
    }}
    
    .watermark {{
      text-align: right;
      color: {watermark_color};
      font-size: {watermark_font}px;
      font-weight: 500;
      padding-top: 16px;
      letter-spacing: 0.5px;
    }}
    
    .logo {{
      position: absolute;
      top: 16px;
      right: 24px;
      opacity: 0.7;
    }}
    
    .logo img {{
      height: 32px;
      width: auto;
    }}
  </style>
</head>
<body>
  {logo_html}
  <div class="messages">
    {messages_html}
  </div>
  <div class="watermark">{"" if logo_html else "Curious Endeavor"}</div>
</body>
</html>'''


def render_to_png(messages: list, output_path: Path, width: int = 1200, height: int = 675, theme: str = "dark", font_scale: float = 1.0, logo_path: str = None, template: str = "default", result_image: str = None):
    """Render messages to PNG using playwright."""
    from playwright.sync_api import sync_playwright
    
    html_content = build_html(messages, theme=theme, font_scale=font_scale, logo_path=logo_path, template=template, result_image=result_image)
    
    with sync_playwright() as p:
        browser = p.chromium.launch()
        page = browser.new_page(viewport={"width": width, "height": height})
        page.set_content(html_content)
        
        # Let fonts load
        page.wait_for_timeout(200)
        
        # Get actual content height
        body_height = page.evaluate("document.body.scrollHeight")
        if body_height > height:
            page.set_viewport_size({"width": width, "height": body_height})
        
        output_path.parent.mkdir(parents=True, exist_ok=True)
        page.screenshot(path=str(output_path))
        browser.close()
    
    return output_path


def main():
    parser = argparse.ArgumentParser(description="Render Discord-style message capture")
    parser.add_argument("--messages", help="Path to JSON file with messages array")
    parser.add_argument("--messages-inline", help="Inline JSON array of messages")
    parser.add_argument("--output", required=True, help="Output PNG path")
    parser.add_argument("--width", type=int, default=1200, help="Image width")
    parser.add_argument("--height", type=int, default=675, help="Minimum image height")
    parser.add_argument("--theme", choices=["dark", "light"], default="dark", help="Color theme")
    parser.add_argument("--font-scale", type=float, default=1.0, help="Font size multiplier (e.g. 1.5 for 50% bigger)")
    parser.add_argument("--logo", help="Path to logo image for top-right corner")
    parser.add_argument("--template", choices=["default", "ce"], default="default", help="Template style")
    parser.add_argument("--result-image", help="Path to result image to show alongside messages")
    
    args = parser.parse_args()
    
    # Load messages
    if args.messages:
        with open(args.messages) as f:
            messages = json.load(f)
    elif args.messages_inline:
        messages = json.loads(args.messages_inline)
    else:
        parser.error("Either --messages or --messages-inline required")
    
    # Handle both {"messages": [...]} and direct [...] formats
    if isinstance(messages, dict) and "messages" in messages:
        messages = messages["messages"]
    
    output_path = Path(args.output)
    result = render_to_png(messages, output_path, args.width, args.height, theme=args.theme, font_scale=args.font_scale, logo_path=args.logo, template=args.template, result_image=args.result_image)
    print(f"✅ Rendered {len(messages)} message(s) to {result}")


if __name__ == "__main__":
    main()
