"""ascii-maker CLI — `am` entry point."""
from __future__ import annotations

import sys

import click
from rich.console import Console
from rich.panel import Panel
from rich.syntax import Syntax
from rich.table import Table
from rich import box as rbox

console = Console()


# ─── Root group ───────────────────────────────────────────────────────────────

@click.group()
@click.version_option("1.0.0", prog_name="ascii-maker")
def cli():
    """ascii-maker (am) — ASCII art designer, chart builder, and README toolkit."""


# ─── TEXT command ──────────────────────────────────────────────────────────────

@cli.command("text")
@click.argument("text")
@click.option("-f", "--font", default="slant", show_default=True, help="Figlet font name")
@click.option("-p", "--pick", is_flag=True, help="Interactive font/color picker")
@click.option("--preview", is_flag=True, help="Preview text in all favorite fonts")
@click.option("--list-fonts", is_flag=True, help="List all available fonts")
@click.option("-g", "--group", default=None, help="Font group for --list-fonts or --preview")
@click.option("--copy", is_flag=True, help="Copy result to clipboard")
def cmd_text(text, font, pick, preview, list_fonts, group, copy):
    """Render TEXT as ASCII art using pyfiglet fonts."""
    from ascii_maker.text_art import render, preview_fonts, interactive_font_picker, list_fonts as lf

    if list_fonts:
        lf(group)
        return

    if preview:
        preview_fonts(text, limit=30)
        return

    if pick:
        art, chosen_font = interactive_font_picker(text)
        console.print(art)
        console.print(f"[dim]Font: {chosen_font}[/]")
    else:
        art = render(text, font)
        console.print(art)

    if copy:
        try:
            import pyperclip
            pyperclip.copy(art)
            console.print("[dim]Copied to clipboard.[/]")
        except Exception:
            console.print("[yellow]pyperclip not available; install it to enable clipboard.[/]")


# ─── BROWSE command ────────────────────────────────────────────────────────────

@cli.command("browse")
@click.argument("category", default="")
@click.option("-n", "--limit", default=20, show_default=True, help="Max results to show")
@click.option("--no-pager", is_flag=True, help="Disable interactive pager")
@click.option("--copy-last", is_flag=True, help="Copy last displayed art to clipboard")
def cmd_browse(category, limit, no_pager, copy_last):
    """Browse ASCII art from asciiart.eu by CATEGORY.

    Leave CATEGORY blank to see all available categories.
    """
    from ascii_maker.browser import fetch_category, browse_interactive, display_arts, search_online

    if not category:
        browse_interactive()
        return

    arts = fetch_category(category, limit=limit)
    last = display_arts(arts, pager=not no_pager)

    if copy_last and last:
        try:
            import pyperclip
            pyperclip.copy(last)
            console.print("[dim]Last art copied to clipboard.[/]")
        except Exception:
            console.print("[yellow]pyperclip not available.[/]")


@cli.command("search")
@click.argument("query")
@click.option("-n", "--limit", default=10, show_default=True)
def cmd_search(query, limit):
    """Search ASCII art by keyword."""
    from ascii_maker.browser import search_online, display_arts
    arts = search_online(query)
    display_arts(arts[:limit])


# ─── BOX command ──────────────────────────────────────────────────────────────

@cli.command("box")
@click.argument("text", nargs=-1)
@click.option("-s", "--style", default="rounded", show_default=True, help="Box style")
@click.option("-t", "--title", default="", help="Box title")
@click.option("-p", "--padding", default=1, show_default=True)
@click.option("--list-styles", is_flag=True, help="List all available box styles")
@click.option("--copy", is_flag=True)
def cmd_box(text, style, title, padding, list_styles, copy):
    """Wrap TEXT in an ASCII/Unicode box.

    Pipe input or pass words as arguments.
    Example:  am box "Hello world"  or  echo "hi" | am box
    """
    from ascii_maker.boxes import make_box, list_styles as ls

    if list_styles:
        console.print(ls())
        return

    if not text and not sys.stdin.isatty():
        content = sys.stdin.read()
    else:
        content = " ".join(text)

    lines = content.splitlines() if content else [""]
    result = make_box(lines, style=style, title=title, padding=padding)
    console.print(result)

    if copy:
        try:
            import pyperclip; pyperclip.copy(result)
            console.print("[dim]Copied.[/]")
        except Exception:
            pass


@cli.command("divider")
@click.argument("style", default="thin")
@click.option("-l", "--label", default="", help="Optional center label")
@click.option("-w", "--width", default=60, show_default=True)
@click.option("--list", "list_divs", is_flag=True, help="List all divider styles")
def cmd_divider(style, label, width, list_divs):
    """Print a divider line.

    STYLE can be: thin, thick, double, dash, dots, shade, flowers, etc.
    """
    from ascii_maker.boxes import make_divider, DIVIDERS, SECTION_DIVIDERS

    if list_divs:
        table = Table(title="Divider Styles", box=rbox.SIMPLE)
        table.add_column("Key", style="cyan")
        table.add_column("Preview")
        for k, v in DIVIDERS.items():
            table.add_row(k, v[:50])
        for k in SECTION_DIVIDERS:
            table.add_row(f"{k} (label)", f"← use with -l 'My Label'")
        console.print(table)
        return

    result = make_divider(style, label=label, width=width)
    console.print(result)


@cli.command("table")
@click.option("-s", "--style", default="single", show_default=True, help="Box style")
@click.option("--header", multiple=True, help="Column headers (repeat flag)")
@click.option("--row", multiple=True, help="Row values as comma-separated (repeat flag)")
def cmd_table(style, header, row):
    """Generate a box-drawing table.

    Example:
      am table --header Name --header Age --header City
               --row "Alice,30,NYC" --row "Bob,25,LA"
    """
    from ascii_maker.boxes import make_table

    if not header:
        console.print("[red]Provide at least one --header[/]")
        return

    headers = list(header)
    rows = [r.split(",") for r in row]
    result = make_table(headers, rows, style=style)
    console.print(result)


@cli.command("tree")
@click.argument("path", default=".")
@click.option("-d", "--depth", default=3, show_default=True, help="Max depth")
def cmd_tree(path, depth):
    """Render a directory as a tree structure."""
    import os
    from ascii_maker.boxes import make_tree

    def scan(p: str, d: int) -> dict | list:
        if d == 0 or not os.path.isdir(p):
            return []
        result = {}
        try:
            entries = sorted(os.listdir(p))
        except PermissionError:
            return []
        for entry in entries:
            if entry.startswith("."):
                continue
            full = os.path.join(p, entry)
            if os.path.isdir(full):
                result[entry] = scan(full, d - 1)
            else:
                result[entry] = ""
        return result

    tree = scan(path, depth)
    console.print(f"[bold]{path}[/]")
    console.print(make_tree(tree))


# ─── CHART commands ────────────────────────────────────────────────────────────

@cli.group("chart")
def cmd_chart():
    """Generate ASCII charts."""


@cmd_chart.command("bar")
@click.argument("values", nargs=-1, type=float)
@click.option("-l", "--labels", default="", help="Comma-separated labels")
@click.option("-t", "--title", default="")
@click.option("-H", "--height", default=15, show_default=True)
@click.option("-w", "--bar-width", default=5, show_default=True)
def chart_bar(values, labels, title, height, bar_width):
    """Vertical bar chart. Pass VALUES as space-separated numbers."""
    from ascii_maker.charts import bar_chart
    if not values:
        console.print("[red]Provide at least one value[/]")
        return
    lbls = [l.strip() for l in labels.split(",")] if labels else None
    console.print(bar_chart(list(values), lbls, title=title, height=height, bar_width=bar_width))


@cmd_chart.command("hbar")
@click.argument("values", nargs=-1, type=float)
@click.option("-l", "--labels", default="", help="Comma-separated labels")
@click.option("-t", "--title", default="")
@click.option("-w", "--width", default=40, show_default=True)
def chart_hbar(values, labels, title, width):
    """Horizontal bar chart."""
    from ascii_maker.charts import hbar_chart
    if not values:
        console.print("[red]Provide at least one value[/]")
        return
    lbls = [l.strip() for l in labels.split(",")] if labels else None
    console.print(hbar_chart(list(values), lbls, title=title, max_width=width))


@cmd_chart.command("line")
@click.argument("values", nargs=-1, type=float)
@click.option("-l", "--labels", default="")
@click.option("-t", "--title", default="")
@click.option("-H", "--height", default=12, show_default=True)
@click.option("-w", "--width", default=60, show_default=True)
def chart_line(values, labels, title, height, width):
    """Line / scatter chart."""
    from ascii_maker.charts import line_chart
    if not values:
        console.print("[red]Provide at least one value[/]")
        return
    lbls = [l.strip() for l in labels.split(",")] if labels else None
    console.print(line_chart(list(values), lbls, title=title, height=height, width=width))


@cmd_chart.command("spark")
@click.argument("values", nargs=-1, type=float)
@click.option("-t", "--title", default="")
def chart_spark(values, title):
    """Single-line sparkline using block chars ▁▂▃▄▅▆▇█."""
    from ascii_maker.charts import sparkline
    if not values:
        console.print("[red]Provide at least one value[/]")
        return
    console.print(sparkline(list(values), title=title))


@cmd_chart.command("pie")
@click.argument("values", nargs=-1, type=float)
@click.option("-l", "--labels", default="")
@click.option("-t", "--title", default="")
def chart_pie(values, labels, title):
    """ASCII pie chart."""
    from ascii_maker.charts import pie_chart
    if not values:
        console.print("[red]Provide at least one value[/]")
        return
    lbls = [l.strip() for l in labels.split(",")] if labels else None
    console.print(pie_chart(list(values), lbls, title=title))


@cmd_chart.command("progress")
@click.argument("value", type=float)
@click.option("-T", "--total", default=100.0, show_default=True)
@click.option("-l", "--label", default="")
@click.option("-w", "--width", default=40, show_default=True)
def chart_progress(value, total, label, width):
    """Single progress bar."""
    from ascii_maker.charts import progress_bar
    console.print(progress_bar(value, total, width=width, label=label))


# ─── MERMAID command ───────────────────────────────────────────────────────────

@cli.command("mermaid")
@click.argument("template", default="")
@click.option("--list", "list_tmpl", is_flag=True, help="List all available templates")
@click.option("--fence", is_flag=True, default=True, show_default=True, help="Wrap in ```mermaid fences")
@click.option("--no-fence", "fence", flag_value=False)
@click.option("--copy", is_flag=True)
def cmd_mermaid(template, list_tmpl, fence, copy):
    """Show or copy a Mermaid diagram template.

    TEMPLATE: flowchart, sequence, class, er, gantt, state, pie, git, mindmap, timeline, ...
    """
    from ascii_maker.mermaid import list_templates, get_template, wrap_in_fence, TEMPLATES

    if list_tmpl or not template:
        console.print(list_templates())
        return

    content = get_template(template)
    if content is None:
        console.print(f"[red]Unknown template '{template}'. Run 'am mermaid --list' to see options.[/]")
        return

    output = wrap_in_fence(content) if fence else content
    syntax = Syntax(output, "markdown", theme="monokai", line_numbers=False)
    console.print(syntax)

    if copy:
        try:
            import pyperclip; pyperclip.copy(output)
            console.print("[dim]Copied to clipboard.[/]")
        except Exception:
            pass


# ─── README command ────────────────────────────────────────────────────────────

@cli.group("readme")
def cmd_readme():
    """README section and badge generators."""


@cmd_readme.command("badge")
@click.argument("preset", default="")
@click.option("--list", "list_badges", is_flag=True)
@click.option("--label", default="", help="Custom badge label")
@click.option("--message", default="", help="Custom badge message")
@click.option("--color", default="blue", show_default=True)
def readme_badge(preset, list_badges, label, message, color):
    """Generate a shields.io badge.

    PRESET: maintained, made-with-python, docker, contributions-welcome, ...
    """
    from ascii_maker.readme import BADGE_PRESETS, badge as mk_badge

    if list_badges or not (preset or label):
        table = Table(title="Badge Presets", box=rbox.SIMPLE)
        table.add_column("Key", style="cyan")
        table.add_column("Markdown")
        for k, v in BADGE_PRESETS.items():
            table.add_row(k, v[:80])
        console.print(table)
        return

    if label and message:
        result = mk_badge(label, message, color)
    else:
        result = BADGE_PRESETS.get(preset, "")
        if not result:
            console.print(f"[red]Unknown preset '{preset}'[/]")
            return

    console.print(result)


@cmd_readme.command("section")
@click.argument("kind")
@click.option("--title", default="")
@click.option("--items", default="", help="Comma-separated list items")
def readme_section(kind, title, items):
    """Generate a README section.

    KIND: features, toc, contributing, license, roadmap, quick-start
    """
    from ascii_maker.readme import (
        features_section, toc, contributing_section,
        license_section, roadmap_section
    )

    item_list = [i.strip() for i in items.split(",") if i.strip()]

    generators = {
        "features": lambda: features_section(item_list, title=title or "Features"),
        "toc": lambda: toc(item_list),
        "contributing": lambda: contributing_section(),
        "license": lambda: license_section(),
        "roadmap": lambda: roadmap_section(item_list[:len(item_list)//2], item_list[len(item_list)//2:]),
    }

    fn = generators.get(kind)
    if fn is None:
        console.print(f"[red]Unknown section kind '{kind}'[/]")
        console.print("Available: " + ", ".join(generators))
        return

    console.print(fn())


@cmd_readme.command("build")
@click.option("--title", prompt="Project title", help="README title")
@click.option("--description", prompt="Short description", help="One-line description")
@click.option("--package", default="", help="PyPI package name (for install section)")
@click.option("--author", default="", help="Author name")
@click.option("-o", "--output", default="README.md", show_default=True, help="Output file")
def readme_build(title, description, package, author, output):
    """Interactively generate a complete README.md."""
    from ascii_maker.readme import build_readme, badge_python, badge_license

    badges = [badge_python(), badge_license()]

    features_raw = click.prompt(
        "Features (comma-separated, or press Enter to skip)", default="", show_default=False
    )
    features = [f.strip() for f in features_raw.split(",") if f.strip()] or None

    content = build_readme(
        title=title,
        description=description,
        features=features,
        install_cmd=package or title.lower().replace(" ", "-"),
        author=author,
        badges=badges,
    )

    with open(output, "w") as f:
        f.write(content)

    console.print(f"[green]✓ README written to {output}[/]")
    console.print(f"  {len(content.splitlines())} lines, {len(content)} bytes")


# ─── BANNER command ────────────────────────────────────────────────────────────

@cli.command("banner")
@click.argument("title")
@click.option("--subtitle", default="", help="Optional subtitle line")
@click.option("-f", "--font", default="slant", show_default=True)
@click.option("-s", "--style", default="double", show_default=True, help="Box style for the banner")
@click.option("--copy", is_flag=True)
def cmd_banner(title, subtitle, font, style, copy):
    """Generate a CLI banner combining ASCII art text + box frame."""
    from ascii_maker.text_art import render
    from ascii_maker.boxes import make_banner, make_box

    art = render(title, font).rstrip()
    art_lines = art.splitlines()

    if subtitle:
        art_lines += ["", subtitle]

    result = make_box(art_lines, style=style, padding=2)
    console.print(result)

    if copy:
        try:
            import pyperclip; pyperclip.copy(result)
            console.print("[dim]Copied.[/]")
        except Exception:
            pass


# ─── DESIGNER command (interactive) ───────────────────────────────────────────

@cli.command("design")
def cmd_design():
    """Launch the interactive ASCII art designer."""
    console.print(Panel(
        "[bold cyan]ASCII Maker — Interactive Designer[/]\n\n"
        "Choose what to create:",
        border_style="cyan",
    ))

    options = [
        ("1", "Text art (pyfiglet fonts)", "text"),
        ("2", "Box / frame", "box"),
        ("3", "Banner (text + frame)", "banner"),
        ("4", "Chart", "chart"),
        ("5", "Mermaid diagram template", "mermaid"),
        ("6", "Browse asciiart.eu", "browse"),
        ("7", "README section / badge", "readme"),
    ]

    for key, label, _ in options:
        console.print(f"  [cyan]{key}[/] {label}")

    choice = console.input("\n[bold]Pick (1-7): [/]").strip()

    mapping = {k: cmd for k, _, cmd in options}
    selected = mapping.get(choice)

    if not selected:
        console.print("[yellow]Invalid choice.[/]")
        return

    console.print(f"\n[dim]Tip: run [cyan]am {selected} --help[/] for all options.[/]\n")

    if selected == "text":
        text = console.input("Text to render: ").strip()
        if text:
            ctx = click.Context(cmd_text)
            cmd_text.invoke(ctx, text=text, font="slant", pick=True, preview=False,
                            list_fonts=False, group=None, copy=False)

    elif selected == "box":
        content = console.input("Text to box: ").strip()
        from ascii_maker.boxes import make_box, list_styles
        console.print(list_styles())
        style = console.input("Box style [rounded]: ").strip() or "rounded"
        title = console.input("Title (optional): ").strip()
        result = make_box(content.splitlines(), style=style, title=title)
        console.print(result)

    elif selected == "banner":
        text = console.input("Banner title: ").strip()
        sub = console.input("Subtitle (optional): ").strip()
        ctx = click.Context(cmd_banner)
        cmd_banner.invoke(ctx, title=text, subtitle=sub, font="slant", style="double", copy=False)

    elif selected == "mermaid":
        from ascii_maker.mermaid import list_templates, get_template, wrap_in_fence
        console.print(list_templates())
        tmpl = console.input("Template name: ").strip()
        content = get_template(tmpl)
        if content:
            console.print(Syntax(wrap_in_fence(content), "markdown", theme="monokai"))
        else:
            console.print(f"[red]Unknown: {tmpl}[/]")

    elif selected == "browse":
        from ascii_maker.browser import browse_interactive
        browse_interactive()

    elif selected == "chart":
        console.print("Chart types: bar, hbar, line, spark, pie, progress")
        kind = console.input("Type: ").strip()
        raw = console.input("Values (space-separated): ").strip()
        try:
            vals = [float(x) for x in raw.split()]
        except ValueError:
            console.print("[red]Invalid numbers[/]")
            return

        from ascii_maker import charts as ch
        chart_fns = {
            "bar": ch.bar_chart, "hbar": ch.hbar_chart,
            "line": ch.line_chart, "spark": ch.sparkline,
            "pie": ch.pie_chart,
        }
        fn = chart_fns.get(kind)
        if fn:
            console.print(fn(vals))
        else:
            console.print(f"[red]Unknown chart type: {kind}[/]")

    elif selected == "readme":
        from ascii_maker.readme import BADGE_PRESETS
        console.print("Sections: features, toc, contributing, license")
        console.print("Badges: " + ", ".join(list(BADGE_PRESETS)[:8]) + " ...")
        console.print("[dim]Use 'am readme --help' for full options.[/]")
