"""
Export automation for mycopunk designs.
Uses Inkscape CLI for SVG to PNG conversion.
"""

import subprocess
import shutil
from pathlib import Path
from typing import Optional

import yaml
from rich.console import Console
from rich.progress import Progress, SpinnerColumn, TextColumn

console = Console()


def get_project_root() -> Path:
    """Find the project root (directory containing designs/)."""
    current = Path.cwd()
    while current != current.parent:
        if (current / "designs").is_dir():
            return current
        current = current.parent
    return Path.cwd()


DESIGNS_DIR = get_project_root() / "designs"


def check_inkscape() -> bool:
    """Check if Inkscape is available."""
    return shutil.which("inkscape") is not None


def export_design(path: str, dpi: int = 300, format: str = "png") -> None:
    """Export a design to print-ready files."""
    design_dir = DESIGNS_DIR / path

    if not design_dir.exists():
        console.print(f"[red]Error: Design not found at {design_dir}[/red]")
        raise SystemExit(1)

    metadata_path = design_dir / "metadata.yaml"
    if not metadata_path.exists():
        console.print("[red]Error: metadata.yaml not found[/red]")
        raise SystemExit(1)

    with open(metadata_path) as f:
        metadata = yaml.safe_load(f)

    source_info = metadata.get("source", {})
    source_file = source_info.get("file")

    if not source_file:
        console.print("[red]Error: No source file specified in metadata[/red]")
        raise SystemExit(1)

    source_path = design_dir / source_file
    if not source_path.exists():
        console.print(f"[red]Error: Source file not found: {source_path}[/red]")
        raise SystemExit(1)

    # Determine export method based on file type
    if source_file.endswith(".svg"):
        export_svg(source_path, design_dir, metadata, dpi, format)
    elif source_file.endswith((".png", ".jpg", ".jpeg")):
        export_raster(source_path, design_dir, metadata, dpi, format)
    else:
        console.print(f"[red]Error: Unsupported source format: {source_file}[/red]")
        raise SystemExit(1)


def export_svg(
    source_path: Path,
    design_dir: Path,
    metadata: dict,
    dpi: int,
    format: str
) -> None:
    """Export SVG using Inkscape."""
    if not check_inkscape():
        console.print("[red]Error: Inkscape not found. Please install Inkscape.[/red]")
        console.print("[dim]Ubuntu: sudo apt install inkscape[/dim]")
        raise SystemExit(1)

    source_info = metadata.get("source", {})
    slug = source_path.stem

    # Create export directory
    export_dir = design_dir / "exports" / f"{dpi}dpi"
    export_dir.mkdir(parents=True, exist_ok=True)

    output_file = export_dir / f"{slug}.{format}"

    with Progress(
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        console=console,
    ) as progress:
        task = progress.add_task(f"Exporting {slug} at {dpi} DPI...", total=None)

        # Build Inkscape command
        cmd = [
            "inkscape",
            str(source_path),
            f"--export-type={format}",
            f"--export-dpi={dpi}",
            f"--export-filename={output_file}",
        ]

        # Add transparent background for PNG
        if format == "png":
            cmd.append("--export-background-opacity=0")

        try:
            result = subprocess.run(
                cmd,
                capture_output=True,
                text=True,
                timeout=120,  # 2 minute timeout
            )

            if result.returncode != 0:
                progress.stop()
                console.print(f"[red]Inkscape error:[/red]\n{result.stderr}")
                raise SystemExit(1)

            progress.update(task, description="Export complete!")

        except subprocess.TimeoutExpired:
            progress.stop()
            console.print("[red]Error: Export timed out[/red]")
            raise SystemExit(1)
        except FileNotFoundError:
            progress.stop()
            console.print("[red]Error: Inkscape not found[/red]")
            raise SystemExit(1)

    # Verify output
    if output_file.exists():
        size_kb = output_file.stat().st_size / 1024
        console.print(f"\n[green]✓ Exported:[/green] {output_file}")
        console.print(f"[dim]  Size: {size_kb:.1f} KB[/dim]")

        # Try to get dimensions using PIL
        try:
            from PIL import Image
            with Image.open(output_file) as img:
                width, height = img.size
                console.print(f"[dim]  Dimensions: {width}×{height} px[/dim]")
        except Exception:
            pass
    else:
        console.print("[red]Error: Export failed - output file not created[/red]")
        raise SystemExit(1)


def export_raster(
    source_path: Path,
    design_dir: Path,
    metadata: dict,
    dpi: int,
    format: str
) -> None:
    """Export/convert raster images using PIL."""
    from PIL import Image

    source_info = metadata.get("source", {})
    slug = source_path.stem

    # Create export directory
    export_dir = design_dir / "exports" / f"{dpi}dpi"
    export_dir.mkdir(parents=True, exist_ok=True)

    output_file = export_dir / f"{slug}.{format}"

    with Progress(
        SpinnerColumn(),
        TextColumn("[progress.description]{task.description}"),
        console=console,
    ) as progress:
        task = progress.add_task(f"Processing {slug}...", total=None)

        try:
            with Image.open(source_path) as img:
                # Convert to appropriate mode
                if format == "png" and img.mode != "RGBA":
                    img = img.convert("RGBA")
                elif format in ("jpg", "jpeg") and img.mode == "RGBA":
                    # Flatten transparency for JPEG
                    background = Image.new("RGB", img.size, (255, 255, 255))
                    background.paste(img, mask=img.split()[3])
                    img = background

                # Save with DPI metadata
                img.save(output_file, dpi=(dpi, dpi))

        except Exception as e:
            progress.stop()
            console.print(f"[red]Error processing image: {e}[/red]")
            raise SystemExit(1)

        progress.update(task, description="Processing complete!")

    # Verify output
    if output_file.exists():
        size_kb = output_file.stat().st_size / 1024
        console.print(f"\n[green]✓ Exported:[/green] {output_file}")
        console.print(f"[dim]  Size: {size_kb:.1f} KB[/dim]")

        with Image.open(output_file) as img:
            width, height = img.size
            console.print(f"[dim]  Dimensions: {width}×{height} px[/dim]")
    else:
        console.print("[red]Error: Export failed[/red]")
        raise SystemExit(1)


def batch_export(
    design_type: Optional[str] = None,
    status: str = "active",
    dpi: int = 300,
    format: str = "png"
) -> None:
    """Export all designs matching criteria."""
    designs_exported = 0
    errors = []

    for category_dir in DESIGNS_DIR.iterdir():
        if not category_dir.is_dir():
            continue

        if design_type and category_dir.name != design_type:
            continue

        for design_dir in category_dir.iterdir():
            if not design_dir.is_dir():
                continue

            metadata_path = design_dir / "metadata.yaml"
            if not metadata_path.exists():
                continue

            try:
                with open(metadata_path) as f:
                    metadata = yaml.safe_load(f)
            except Exception:
                continue

            design_status = metadata.get("status", "unknown")
            if design_status != status:
                continue

            path = f"{category_dir.name}/{design_dir.name}"
            console.print(f"\n[bold]Exporting: {path}[/bold]")

            try:
                export_design(path, dpi, format)
                designs_exported += 1
            except SystemExit:
                errors.append(path)

    console.print(f"\n[green]Exported {designs_exported} design(s)[/green]")
    if errors:
        console.print(f"[red]Failed: {len(errors)} design(s)[/red]")
        for e in errors:
            console.print(f"  [red]• {e}[/red]")
