"""Render HTML to image command implementation."""

import base64
from pathlib import Path

import typer

from cli.infrastructure.command import async_command, authenticated_client
from cli.infrastructure.file_content import FileContentError, resolve_content
from cli.infrastructure.output import OutputService
from cli.infrastructure.spinner import spinner
from alloy_runtime_types.dtos.render import RenderHtmlToImageRequest


def render_html_to_image_command(
    html: str = typer.Option(
        ...,
        "-h",
        "--html",
        help="HTML text to render (or @file to read from file)",
    ),
    output_file: str = typer.Option(
        ...,
        "-o",
        "--output",
        help="Output file path for the PNG image",
    ),
    bg_color: str = typer.Option(
        "#ffffff",
        "--bg",
        "--background",
        help="Background color in hex format (default: white)",
    ),
    text_color: str = typer.Option(
        "#000000",
        "--fg",
        "--foreground",
        help="Text color in hex format (default: black)",
    ),
    font_family: str = typer.Option(
        "Georgia, serif",
        "--font",
        help="CSS font-family value (used as fallback when --font-url is provided)",
    ),
    font_url: str | None = typer.Option(
        None,
        "--font-url",
        help="Google Fonts URL (font name is auto-extracted from URL)",
    ),
    width: int = typer.Option(
        1080,
        "-W",
        "--width",
        min=100,
        max=4096,
        help="Image width in pixels (default: 1080 for social media)",
    ),
    height: int = typer.Option(
        1080,
        "-H",
        "--height",
        min=100,
        max=4096,
        help="Image height in pixels (default: 1080 for social media)",
    ),
) -> None:
    """Render HTML text to a PNG image.

    Creates a square 1080x1080 image by default, perfect for social media ads
    (Instagram, Facebook). Uses white background with black text.

    Examples:

        # Basic usage with inline HTML
        alloy render image -h "<strong>Hello</strong> World!" -o output.png

        # Read HTML from file
        alloy render image -h @content.html -o output.png

        # Custom colors (dark mode)
        alloy render image -h "Dark mode" -o dark.png --bg "#1a1a1a" --fg "#ffffff"

        # Custom dimensions (Instagram story: 1080x1920)
        alloy render image -h "Story" -o story.png -W 1080 -H 1920

        # Custom font
        alloy render image -h "Custom" -o custom.png --font "Arial, sans-serif"

        # Google Font (font name auto-extracted from URL)
        alloy render image -h "Elegant" -o elegant.png \\
            --font-url "https://fonts.googleapis.com/css2?family=Playfair+Display:wght@700"
    """
    # Resolve @file references for HTML content
    try:
        resolved_html = resolve_content(html)
    except FileContentError as e:
        raise typer.BadParameter(str(e))

    if not resolved_html:
        raise typer.BadParameter("HTML content cannot be empty")

    # Validate hex color format
    import re

    hex_pattern = r"^#[0-9a-fA-F]{6}$"
    if not re.match(hex_pattern, bg_color):
        raise typer.BadParameter(
            f"Invalid background color '{bg_color}'. Use hex format like #ffffff"
        )
    if not re.match(hex_pattern, text_color):
        raise typer.BadParameter(
            f"Invalid text color '{text_color}'. Use hex format like #000000"
        )

    _execute_render(
        html=resolved_html,
        output_file=output_file,
        bg_color=bg_color,
        text_color=text_color,
        font_family=font_family,
        font_url=font_url,
        width=width,
        height=height,
    )


@async_command
async def _execute_render(
    html: str,
    output_file: str,
    bg_color: str,
    text_color: str,
    font_family: str,
    font_url: str | None,
    width: int,
    height: int,
) -> None:
    """Execute the render HTML to image API call."""
    output = OutputService.get()

    async with authenticated_client() as (_config, client):
        request = RenderHtmlToImageRequest(
            html_text=html,
            bg_color=bg_color,
            text_color=text_color,
            font_family=font_family,
            font_url=font_url,
            width=width,
            height=height,
        )

        async with spinner(f"Rendering {width}x{height} image..."):
            response = await client.render_html_to_image(request)

    # Decode base64 and write to file
    image_bytes = base64.b64decode(response.image_base64)
    output_path = Path(output_file)

    # Create parent directories if needed
    output_path.parent.mkdir(parents=True, exist_ok=True)

    # Write the image
    output_path.write_bytes(image_bytes)

    file_size_kb = len(image_bytes) / 1024
    output.result(
        action="write",
        resource="image",
        identifier=None,
        name=output_path.name,
        extra_fields={
            "Path": str(output_path),
            "Width": response.width,
            "Height": response.height,
            "Size": f"{file_size_kb:.1f} KB",
            "Render Time": f"{response.render_time_ms} ms",
        },
    )
