"""Box, frame, divider, and border designer for CLI tools and READMEs."""
from __future__ import annotations

# ─── Box-drawing character sets ──────────────────────────────────────────────

STYLES: dict[str, dict] = {
    "single": {
        "tl": "┌", "tr": "┐", "bl": "└", "br": "┘",
        "h": "─", "v": "│", "lt": "├", "rt": "┤", "tt": "┬", "bt": "┴", "cross": "┼",
        "name": "Single Line",
    },
    "double": {
        "tl": "╔", "tr": "╗", "bl": "╚", "br": "╝",
        "h": "═", "v": "║", "lt": "╠", "rt": "╣", "tt": "╦", "bt": "╩", "cross": "╬",
        "name": "Double Line",
    },
    "rounded": {
        "tl": "╭", "tr": "╮", "bl": "╰", "br": "╯",
        "h": "─", "v": "│", "lt": "├", "rt": "┤", "tt": "┬", "bt": "┴", "cross": "┼",
        "name": "Rounded",
    },
    "thick": {
        "tl": "┏", "tr": "┓", "bl": "┗", "br": "┛",
        "h": "━", "v": "┃", "lt": "┣", "rt": "┫", "tt": "┳", "bt": "┻", "cross": "╋",
        "name": "Thick",
    },
    "ascii": {
        "tl": "+", "tr": "+", "bl": "+", "br": "+",
        "h": "-", "v": "|", "lt": "+", "rt": "+", "tt": "+", "bt": "+", "cross": "+",
        "name": "ASCII (safe)",
    },
    "hash": {
        "tl": "#", "tr": "#", "bl": "#", "br": "#",
        "h": "#", "v": "#", "lt": "#", "rt": "#", "tt": "#", "bt": "#", "cross": "#",
        "name": "Hash/Pound",
    },
    "star": {
        "tl": "*", "tr": "*", "bl": "*", "br": "*",
        "h": "*", "v": "*", "lt": "*", "rt": "*", "tt": "*", "bt": "*", "cross": "*",
        "name": "Stars",
    },
    "dot": {
        "tl": "·", "tr": "·", "bl": "·", "br": "·",
        "h": "·", "v": "·", "lt": "·", "rt": "·", "tt": "·", "bt": "·", "cross": "·",
        "name": "Dots",
    },
}

# ─── Divider styles ───────────────────────────────────────────────────────────

DIVIDERS: dict[str, str] = {
    "thin":        "─" * 60,
    "thick":       "━" * 60,
    "double":      "═" * 60,
    "dash":        "- " * 30,
    "dots":        "· " * 30,
    "star":        "* " * 30,
    "wave":        "~" * 60,
    "equals":      "=" * 60,
    "hash":        "#" * 60,
    "arrows-r":    ">" * 60,
    "arrows-l":    "<" * 60,
    "zigzag":      "/\\" * 30,
    "slash":       "/" * 60,
    "backslash":   "\\" * 60,
    "block":       "█" * 60,
    "shade":       "░▒▓█▓▒░" * 8,
    "flowers":     "✿ " * 20,
    "diamonds":    "◆ " * 20,
    "triangles":   "▶ " * 20,
    "hearts":      "♥ " * 20,
    "sparkle":     "✦ " * 20,
    "wavy":        "≈" * 60,
    "double-wave": "≋" * 60,
    "section":     "§" * 60,
    "pilcrow":     "¶" * 60,
    "cross":       "✚ " * 20,
    "snowflake":   "❄ " * 20,
    "bullet":      "• " * 30,
    "dash-dot":    "─·─·─·" * 10,
    "bracket":     "[ " + "─" * 56 + " ]",
}

# Labeled divider templates for CLI output
SECTION_DIVIDERS = {
    "banner": lambda t: f"{'━' * 4} {t} {'━' * (55 - len(t))}",
    "comment": lambda t: f"# {'─' * 3} {t} {'─' * (51 - len(t))} #",
    "arrow": lambda t: f"──▶ {t}",
    "bracket": lambda t: f"[{t}]{'─' * (58 - len(t))}",
    "hash": lambda t: f"## {t}",
    "double-hash": lambda t: f"### {t} ###",
    "stars": lambda t: f"{'*' * 4} {t} {'*' * (51 - len(t))}",
    "pipes": lambda t: f"│ {t}",
    "dash-label": lambda t: f"---- {t} ----",
    "section": lambda t: f"\n{'═' * 60}\n  {t}\n{'═' * 60}",
}


def make_box(
    lines: list[str],
    style: str = "rounded",
    title: str = "",
    padding: int = 1,
    width: int = 0,
) -> str:
    """Wrap lines in a box using the given style."""
    s = STYLES.get(style, STYLES["rounded"])

    inner_w = max((len(l) for l in lines), default=20) + padding * 2
    if title:
        inner_w = max(inner_w, len(title) + 4)
    if width:
        inner_w = max(inner_w, width - 2)

    pad = " " * padding
    out: list[str] = []

    # Top border
    if title:
        t = f" {title} "
        fill = inner_w - len(t)
        left = fill // 2
        right = fill - left
        out.append(s["tl"] + s["h"] * left + t + s["h"] * right + s["tr"])
    else:
        out.append(s["tl"] + s["h"] * inner_w + s["tr"])

    # Content lines
    for line in lines:
        padded = pad + line + " " * (inner_w - len(line) - padding * 2) + pad
        out.append(s["v"] + padded + s["v"])

    # Bottom border
    out.append(s["bl"] + s["h"] * inner_w + s["br"])

    return "\n".join(out)


def make_divider(style: str = "thin", label: str = "", width: int = 60) -> str:
    """Generate a divider line, optionally with a label."""
    if label and style in SECTION_DIVIDERS:
        return SECTION_DIVIDERS[style](label)

    if style in DIVIDERS:
        base = DIVIDERS[style]
        if label:
            half = (width - len(label) - 2) // 2
            char = base[0] if base else "─"
            return char * half + f" {label} " + char * (width - half - len(label) - 2)
        return base[:width]

    # Fallback: use char * width
    char = style[0] if style else "─"
    return char * width


def make_banner(title: str, subtitle: str = "", style: str = "double") -> str:
    """Create a full-width banner box."""
    lines = [title]
    if subtitle:
        lines.append("")
        lines.append(subtitle)
    return make_box(lines, style=style, padding=2)


def make_table(
    headers: list[str],
    rows: list[list[str]],
    style: str = "single",
) -> str:
    """Create a text table with box-drawing characters."""
    s = STYLES.get(style, STYLES["single"])

    # Calculate column widths
    widths = [len(h) for h in headers]
    for row in rows:
        for i, cell in enumerate(row):
            if i < len(widths):
                widths[i] = max(widths[i], len(str(cell)))

    def row_str(cells: list[str], left: str, mid: str, right: str, fill: str = " ") -> str:
        parts = []
        for i, cell in enumerate(cells):
            w = widths[i] if i < len(widths) else 10
            parts.append(f" {str(cell):<{w}} ")
        return left + mid.join(parts) + right

    def sep(left: str, mid: str, right: str) -> str:
        parts = [s["h"] * (widths[i] + 2) for i in range(len(headers))]
        return left + mid.join(parts) + right

    out = []
    out.append(sep(s["tl"], s["tt"], s["tr"]))
    out.append(row_str(headers, s["v"], s["v"], s["v"]))
    out.append(sep(s["lt"], s["cross"], s["rt"]))
    for row in rows:
        out.append(row_str(row, s["v"], s["v"], s["v"]))
    out.append(sep(s["bl"], s["bt"], s["br"]))

    return "\n".join(out)


def make_tree(items: dict | list, prefix: str = "", last: bool = True) -> str:
    """Generate a directory/tree structure."""
    lines = []
    if isinstance(items, list):
        for i, item in enumerate(items):
            is_last = i == len(items) - 1
            connector = "└── " if is_last else "├── "
            lines.append(prefix + connector + str(item))
    elif isinstance(items, dict):
        keys = list(items.keys())
        for i, (key, val) in enumerate(items.items()):
            is_last = i == len(keys) - 1
            connector = "└── " if is_last else "├── "
            lines.append(prefix + connector + str(key) + "/")
            extension = "    " if is_last else "│   "
            if isinstance(val, (dict, list)):
                sub = make_tree(val, prefix + extension, is_last)
                if sub:
                    lines.append(sub)
            elif val:
                lines.append(prefix + extension + "└── " + str(val))
    return "\n".join(lines)


def list_styles() -> str:
    """Return a preview of all box styles."""
    out = []
    for key, s in STYLES.items():
        sample = (
            s["tl"] + s["h"] * 7 + s["tr"] + "\n"
            + s["v"] + f" {s['name']:<5} " + s["v"] + "\n"
            + s["bl"] + s["h"] * 7 + s["br"]
        )
        out.append(f"[{key}]\n{sample}")
    return "\n\n".join(out)
