"""Linear Canal — shared brand / splash module.

All commands that show a splash screen import from here.
Zero external dependencies — pure Python + ANSI escape codes.
"""

from __future__ import annotations

import math
import sys
import time
from typing import Optional

# ─── ANSI constants ───────────────────────────────────────────────────────────

_R = "\033[0m"          # reset
_B = "\033[1m"          # bold
_D = "\033[2m"          # dim

# Brand palette — silver gradient (bright top → dark bottom) + monochrome UI
_GLOW      = "\033[1;97m"       # bold bright white  — glow flash (phase 2)
_PRIMARY   = "\033[38;5;252m"   # near-white         — fallback / secondary text
_SECONDARY = "\033[38;5;252m"   # near-white         — secondary text
_WHITE     = "\033[38;5;252m"   # near-white         — primary text
_GREY      = "\033[38;5;244m"   # #808080            — muted text

# Per-line gradient for the 6-row ASCII logo: top = brightest, bottom = darkest
_GRAD = [
    "\033[38;5;255m",   # line 0 — #eeeeee  near-white top
    "\033[38;5;253m",   # line 1 — #dadada
    "\033[38;5;250m",   # line 2 — #bcbcbc
    "\033[38;5;247m",   # line 3 — #9e9e9e
    "\033[38;5;244m",   # line 4 — #808080
    "\033[38;5;241m",   # line 5 — #626262  dark bottom
]

# ─── ASCII title ──────────────────────────────────────────────────────────────

_LC_ASCII = [
    "  ██╗     ██╗███╗   ██╗███████╗ █████╗ ██████╗      ██████╗ █████╗ ███╗   ██╗ █████╗ ██╗",
    "  ██║     ██║████╗  ██║██╔════╝██╔══██╗██╔══██╗    ██╔════╝██╔══██╗████╗  ██║██╔══██╗██║",
    "  ██║     ██║██╔██╗ ██║█████╗  ███████║██████╔╝    ██║     ███████║██╔██╗ ██║███████║██║",
    "  ██║     ██║██║╚██╗██║██╔══╝  ██╔══██║██╔══██╗    ██║     ██╔══██║██║╚██╗██║██╔══██║██║",
    "  ███████╗██║██║ ╚████║███████╗██║  ██║██║  ██║    ╚██████╗██║  ██║██║ ╚████║██║  ██║███████╗",
    "  ╚══════╝╚═╝╚═╝  ╚═══╝╚══════╝╚═╝  ╚═╝╚═╝  ╚═╝     ╚═════╝╚═╝  ╚═╝╚═╝  ╚═══╝╚═╝  ╚═╝╚══════╝",
]

# ─── Animated banner (title only) ─────────────────────────────────────────────

def animated_banner() -> None:
    """Animated ASCII title — 4-phase glow effect.

    Phase 1 — build line-by-line in brand amber.
    Phase 2 — glow flash (bright yellow).
    Phase 3 — settle back to brand amber.
    Phase 4 — typewriter tagline in brand teal.

    No-ops gracefully when stdout is not a TTY.
    """
    out = sys.stdout
    tty = out.isatty()
    n   = len(_LC_ASCII)

    if tty and sys.platform == "win32":
        try:
            import ctypes
            k = ctypes.windll.kernel32  # type: ignore[attr-defined]
            k.SetConsoleMode(k.GetStdHandle(-11), 7)
        except Exception:
            pass

    out.write("\n")

    if not tty:
        for i, line in enumerate(_LC_ASCII):
            out.write(f"{_GRAD[i]}{line}{_R}\n")
        out.write("\n")
        out.flush()
        return

    # Phase 1 — build line by line with silver gradient
    for i, line in enumerate(_LC_ASCII):
        out.write(f"{_GRAD[i]}{line}{_R}\n")
        out.flush()
        time.sleep(0.07)

    # Phase 2 — glow flash (all bright white)
    time.sleep(0.10)
    out.write(f"\033[{n}A")
    for line in _LC_ASCII:
        out.write(f"\033[2K{_GLOW}{line}{_R}\n")
    out.flush()
    time.sleep(0.14)

    # Phase 3 — settle back to gradient
    out.write(f"\033[{n}A")
    for i, line in enumerate(_LC_ASCII):
        out.write(f"\033[2K{_GRAD[i]}{line}{_R}\n")
    out.flush()

    # Phase 4 — typewriter tagline
    tagline = "Context Intelligence Layer"
    out.write(f"\n    {_SECONDARY}")
    out.flush()
    for ch in tagline:
        out.write(ch)
        out.flush()
        time.sleep(0.030)
    out.write(f"{_R}{_D}  —  v0.2.0{_R}\n\n")
    out.flush()


# ─── Static vortex snapshot ───────────────────────────────────────────────────

_V_COLS = 28
_V_ROWS = 20

# ANSI RGB helpers (inline — avoid importing intro.py)
def _c(r: int, g: int, b: int) -> str:
    return f"\x1b[38;2;{r};{g};{b}m"

_G1 = _c(255, 255, 255)  # bright white — primary highlight
_G2 = _c(200, 200, 200)  # light gray   — secondary
_G3 = _c(136, 136, 136)  # mid gray     — Vercel muted #888888
_G4 = _c(68,  68,  68)   # dark gray    — Vercel border #444444
_CY = _c(230, 230, 230)  # near-white   — core pulse
_TE = _c(164, 164, 164)  # gray #a4a4a4 — mid-orbit (Vercel muted-foreground)


def _render_vortex(tick: int) -> list[str]:
    cx = _V_COLS // 2
    cy = _V_ROWS // 2
    grid: list[list[Optional[tuple[str, str, int]]]] = [
        [None] * _V_COLS for _ in range(_V_ROWS)
    ]

    def _set(gx: int, gy: int, ch: str, color: str, layer: int = 1) -> None:
        if gy < 0 or gy >= _V_ROWS or gx < 0 or gx >= _V_COLS:
            return
        existing = grid[gy][gx]
        if existing is not None and existing[2] >= layer:
            return
        grid[gy][gx] = (ch, color, layer)

    # Outer orbit — 3 particles with trails
    o_r = 7.5
    for p in range(3):
        a = tick * 0.022 + (p * math.pi * 2) / 3
        _set(round(cx + o_r * math.cos(a) * 1.9),
             round(cy + o_r * math.sin(a) * 0.62), "◈", _G1, 3)
        for t in range(1, 6):
            ta = a - t * 0.11
            ch    = "◇" if t == 1 else "·"
            color = _G2 if t == 1 else (_G3 if t <= 3 else _G4)
            _set(round(cx + o_r * math.cos(ta) * 1.9),
                 round(cy + o_r * math.sin(ta) * 0.62), ch, color, 2)

    # Mid orbit — 4 reverse particles
    m_r = 4.8
    for p in range(4):
        a = -tick * 0.034 + (p * math.pi * 2) / 4
        _set(round(cx + m_r * math.cos(a) * 1.8),
             round(cy + m_r * math.sin(a) * 0.7), "○", _TE, 3)
        for t in range(1, 3):
            ta = a + t * 0.18
            _set(round(cx + m_r * math.cos(ta) * 1.8),
                 round(cy + m_r * math.sin(ta) * 0.7), "·", _G4, 2)

    # DNA helix
    for dx in range(-8, 9):
        a  = dx * 0.52 + tick * 0.028
        y1 = round(cy + 1.85 * math.sin(a))
        y2 = round(cy + 1.85 * math.sin(a + math.pi))
        gx = cx + dx
        _set(gx, y1, "█", _G1, 4)
        _set(gx, y2, "█", _G2, 4)
        if abs(y1 - y2) <= 2:
            _set(gx, round((y1 + y2) / 2), "─", _G3, 3)

    # Floating dots
    for i in range(4):
        gy = cy - 6 + round(1.5 * math.sin(tick * 0.04 + i * 1.6))
        _set(cx - 4 + i * 3, gy, "·", _G4, 1)

    # Core pulse (fixed at static frame)
    pulse = ["◉", "●", "◎", "●"]
    _set(cx, cy, pulse[(tick // 7) % 4], _CY, 5)

    rows: list[str] = []
    for row in grid:
        line = ""
        for cell in row:
            if cell is None:
                line += " "
            else:
                ch, color, _ = cell
                line += color + ch + "\x1b[0m"
        rows.append(line)
    return rows


# Pre-compute the static vortex snapshot once at module load (tick=28 looks good)
_VORTEX: list[str] = _render_vortex(28)


# ─── Divider ──────────────────────────────────────────────────────────────────

def _divider(version: str = "0.2.0") -> str:
    label = f" Linear Canal v{version} "
    bar   = "─" * 20
    return f"  {_D}{bar}{_R}{_WHITE}{label}{_R}{_D}{bar}{_R}\n"


# ─── Pipeline panel (right column) ────────────────────────────────────────────

def pipeline_panel() -> list[str]:
    """Return the right-side info panel lines for the setup splash."""

    def hd(s: str) -> str:
        return f"{_B}{_WHITE}{s}{_R}"

    def kv(key: str, val: str, note: str = "") -> str:
        note_part = f"  {_GREY}{note}{_R}" if note else ""
        return f"  {_D}{key}{_R}{_WHITE}{val}{_R}{note_part}"

    return [
        hd("Pipeline"),
        kv("①  Scout         ", "parse imports",       "· build dependency graph"),
        kv("②  Graph Engine  ", "centrality scoring",  "· tier ranking"),
        kv("③  Ctx Compiler  ", "write .ctx files",    "· agent instruction prompts"),
        kv("④  Indexer       ", "embed + store",       "→ LanceDB"),
        "",
        hd("Vector Store"),
        kv("engine     ", "LanceDB",                "embedded · no server required"),
        kv("model      ", "BAAI/bge-small-en-v1.5", ""),
        kv("dimension  ", "384-dim",                ""),
        "",
        hd("Agents Supported"),
        f"  {_WHITE}Claude Code{_R} · {_WHITE}Cursor{_R} · {_WHITE}Gemini CLI{_R} · {_WHITE}Copilot{_R}",
        f"  {_WHITE}Windsurf{_R} · {_WHITE}Roo{_R} · {_WHITE}Kilo{_R} · {_WHITE}Cline{_R} · {_WHITE}OpenCode{_R} {_GREY}+ 7 more{_R}",
    ]


# ─── Two-column renderer ──────────────────────────────────────────────────────

def _render_two_col(left: list[str], right: list[str], gap: int = 4) -> None:
    """Print left and right columns side-by-side.

    Left column rows are raw ANSI strings (visual width = _V_COLS chars).
    Right column rows are raw ANSI strings (variable width).
    """
    height = max(len(left), len(right))
    out    = sys.stdout
    for i in range(height):
        lrow = left[i]  if i < len(left)  else ""
        rrow = right[i] if i < len(right) else ""
        out.write("  " + lrow + " " * gap + rrow + "\n")
    out.write("\n")
    out.flush()


# ─── Public entry point ───────────────────────────────────────────────────────

def show_header() -> None:
    """Full Hermes-style splash for linear-canal setup.

    1. Animated ASCII title (4-phase glow).
    2. Centered ── Linear Canal v0.2.0 ── divider.
    3. Two-column block: static vortex (left) + pipeline panel (right).
    """
    animated_banner()
    sys.stdout.write("\n")
    sys.stdout.write(_divider())
    sys.stdout.write("\n")
    sys.stdout.flush()
    _render_two_col(_VORTEX, pipeline_panel())
