#!/usr/bin/env bun

/**
 * Banner - Neofetch-Style PAI Banner
 * Split-pane layout with ASCII art + system stats
 * Tokyo Night color palette with semantic hierarchy
 *
 * Modes:
 *   - nano   (<40):  Minimal colored status line
 *   - micro  (40-59): Compact box with key stats
 *   - mini   (60-84): Small split-pane layout
 *   - normal (85+):   Full neofetch-style banner
 */

import { readdirSync, existsSync, readFileSync } from "fs";
import { join } from "path";
import { spawnSync } from "child_process";

const HOME = process.env.HOME!;
const CLAUDE_DIR = join(HOME, ".claude");

// ═══════════════════════════════════════════════════════════════════════
// Terminal Width Detection
// ═══════════════════════════════════════════════════════════════════════

type DisplayMode = "nano" | "micro" | "mini" | "normal";

function getTerminalWidth(): number {
  let width: number | null = null;

  // Tier 1: Kitty IPC
  const kittyWindowId = process.env.KITTY_WINDOW_ID;
  if (kittyWindowId) {
    try {
      const result = spawnSync("kitten", ["@", "ls"], { encoding: "utf-8" });
      if (result.stdout) {
        const data = JSON.parse(result.stdout);
        for (const osWindow of data) {
          for (const tab of osWindow.tabs) {
            for (const win of tab.windows) {
              if (win.id === parseInt(kittyWindowId)) {
                width = win.columns;
                break;
              }
            }
          }
        }
      }
    } catch {}
  }

  // Tier 2: Direct TTY query
  if (!width || width <= 0) {
    try {
      const result = spawnSync("sh", ["-c", "stty size </dev/tty 2>/dev/null"], {
        encoding: "utf-8"
      });
      if (result.stdout) {
        const cols = parseInt(result.stdout.trim().split(/\s+/)[1]);
        if (cols > 0) width = cols;
      }
    } catch {}
  }

  // Tier 3: tput fallback
  if (!width || width <= 0) {
    try {
      const result = spawnSync("tput", ["cols"], { encoding: "utf-8" });
      if (result.stdout) {
        const cols = parseInt(result.stdout.trim());
        if (cols > 0) width = cols;
      }
    } catch {}
  }

  // Tier 4: Environment variable fallback
  if (!width || width <= 0) {
    width = parseInt(process.env.COLUMNS || "80") || 80;
  }

  return width;
}

function getDisplayMode(): DisplayMode {
  const width = getTerminalWidth();
  if (width < 40) return "nano";
  if (width < 60) return "micro";
  if (width < 85) return "mini";
  return "normal";
}

// ═══════════════════════════════════════════════════════════════════════
// ANSI & Tokyo Night Color System
// ═══════════════════════════════════════════════════════════════════════

const RESET = "\x1b[0m";
const BOLD = "\x1b[1m";
const DIM = "\x1b[2m";

const rgb = (r: number, g: number, b: number) => `\x1b[38;2;${r};${g};${b}m`;

// Tokyo Night Storm palette - rich, vibrant colors
const COLORS = {
  // Brand gradient for ASCII art
  blue: rgb(122, 162, 247),       // #7aa2f7 - primary blue
  magenta: rgb(187, 154, 247),    // #bb9af7 - purple
  cyan: rgb(125, 207, 255),       // #7dcfff - bright cyan

  // Semantic colors
  green: rgb(158, 206, 106),      // #9ece6a - success/active
  orange: rgb(255, 158, 100),     // #ff9e64 - accent/highlight
  red: rgb(247, 118, 142),        // #f7768e - error/warning
  yellow: rgb(224, 175, 104),     // #e0af68 - caution

  // UI colors
  frame: rgb(59, 66, 97),         // #3b4261 - borders (slightly brighter)
  text: rgb(169, 177, 214),       // #a9b1d6 - primary text
  subtext: rgb(86, 95, 137),      // #565f89 - secondary/dim text
  bright: rgb(192, 202, 245),     // #c0caf5 - bright text
};

// Letter colors for name gradient
const LETTER_COLORS = [COLORS.blue, COLORS.magenta, COLORS.cyan];

// ═══════════════════════════════════════════════════════════════════════
// Unicode Elements
// ═══════════════════════════════════════════════════════════════════════

const BOX = {
  topLeft: "╭",
  topRight: "╮",
  bottomLeft: "╰",
  bottomRight: "╯",
  horizontal: "─",
  vertical: "│",
  leftT: "├",
  rightT: "┤",
};

const STATUS = {
  check: "✓",
  circle: "○",
  filled: "●",
  diamond: "◆",
  arrow: "→",
  bar: "│",
};

// ═══════════════════════════════════════════════════════════════════════
// Block Letter Definitions (5 rows - compact)
// ═══════════════════════════════════════════════════════════════════════

const LETTERS: Record<string, string[]> = {
  A: [
    " █████╗ ",
    "██╔══██╗",
    "███████║",
    "██╔══██║",
    "██║  ██║",
  ],
  B: [
    "██████╗ ",
    "██╔══██╗",
    "██████╔╝",
    "██╔══██╗",
    "██████╔╝",
  ],
  C: [
    " ██████╗",
    "██╔════╝",
    "██║     ",
    "██║     ",
    "╚██████╗",
  ],
  D: [
    "██████╗ ",
    "██╔══██╗",
    "██║  ██║",
    "██║  ██║",
    "██████╔╝",
  ],
  E: [
    "███████╗",
    "██╔════╝",
    "█████╗  ",
    "██╔══╝  ",
    "███████╗",
  ],
  F: [
    "███████╗",
    "██╔════╝",
    "█████╗  ",
    "██╔══╝  ",
    "██║     ",
  ],
  G: [
    " ██████╗ ",
    "██╔════╝ ",
    "██║  ███╗",
    "██║   ██║",
    "╚██████╔╝",
  ],
  H: [
    "██╗  ██╗",
    "██║  ██║",
    "███████║",
    "██╔══██║",
    "██║  ██║",
  ],
  I: [
    "██╗",
    "██║",
    "██║",
    "██║",
    "██║",
  ],
  J: [
    "     ██╗",
    "     ██║",
    "     ██║",
    "██   ██║",
    "╚█████╔╝",
  ],
  K: [
    "██╗  ██╗",
    "██║ ██╔╝",
    "█████╔╝ ",
    "██╔═██╗ ",
    "██║  ██╗",
  ],
  L: [
    "██╗     ",
    "██║     ",
    "██║     ",
    "██║     ",
    "███████╗",
  ],
  M: [
    "███╗   ███╗",
    "████╗ ████║",
    "██╔████╔██║",
    "██║╚██╔╝██║",
    "██║ ╚═╝ ██║",
  ],
  N: [
    "███╗   ██╗",
    "████╗  ██║",
    "██╔██╗ ██║",
    "██║╚██╗██║",
    "██║ ╚████║",
  ],
  O: [
    " ██████╗ ",
    "██╔═══██╗",
    "██║   ██║",
    "██║   ██║",
    "╚██████╔╝",
  ],
  P: [
    "██████╗ ",
    "██╔══██╗",
    "██████╔╝",
    "██╔═══╝ ",
    "██║     ",
  ],
  Q: [
    " ██████╗ ",
    "██╔═══██╗",
    "██║   ██║",
    "██║▄▄ ██║",
    "╚██████╔╝",
  ],
  R: [
    "██████╗ ",
    "██╔══██╗",
    "██████╔╝",
    "██╔══██╗",
    "██║  ██║",
  ],
  S: [
    "███████╗",
    "██╔════╝",
    "███████╗",
    "╚════██║",
    "███████║",
  ],
  T: [
    "████████╗",
    "╚══██╔══╝",
    "   ██║   ",
    "   ██║   ",
    "   ██║   ",
  ],
  U: [
    "██╗   ██╗",
    "██║   ██║",
    "██║   ██║",
    "██║   ██║",
    "╚██████╔╝",
  ],
  V: [
    "██╗   ██╗",
    "██║   ██║",
    "██║   ██║",
    "╚██╗ ██╔╝",
    " ╚████╔╝ ",
  ],
  W: [
    "██╗    ██╗",
    "██║    ██║",
    "██║ █╗ ██║",
    "██║███╗██║",
    "╚███╔███╔╝",
  ],
  X: [
    "██╗  ██╗",
    "╚██╗██╔╝",
    " ╚███╔╝ ",
    " ██╔██╗ ",
    "██╔╝ ██╗",
  ],
  Y: [
    "██╗   ██╗",
    "╚██╗ ██╔╝",
    " ╚████╔╝ ",
    "  ╚██╔╝  ",
    "   ██║   ",
  ],
  Z: [
    "███████╗",
    "╚══███╔╝",
    "  ███╔╝ ",
    " ███╔╝  ",
    "███████╗",
  ],
  " ": ["   ", "   ", "   ", "   ", "   "],
};

// ═══════════════════════════════════════════════════════════════════════
// Dynamic Stats & Identity
// ═══════════════════════════════════════════════════════════════════════

interface SystemStats {
  name: string;
  skills: number;
  userFiles: number;
  hooks: number;
  sessions: number;
  model: string;
}

function readDAIdentity(): string {
  const settingsPath = join(CLAUDE_DIR, "settings.json");
  try {
    const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
    return settings.daidentity?.displayName || settings.daidentity?.name || settings.env?.DA || "KAI";
  } catch {
    return "KAI";
  }
}

function countSkills(): number {
  const skillsDir = join(CLAUDE_DIR, "skills");
  if (!existsSync(skillsDir)) return 0;
  let count = 0;
  try {
    for (const entry of readdirSync(skillsDir, { withFileTypes: true })) {
      if (entry.isDirectory() && existsSync(join(skillsDir, entry.name, "SKILL.md"))) count++;
    }
  } catch {}
  return count;
}

function countUserFiles(): number {
  const userDir = join(CLAUDE_DIR, "skills/CORE/USER");
  if (!existsSync(userDir)) return 0;
  let count = 0;
  const countRecursive = (dir: string) => {
    try {
      for (const entry of readdirSync(dir, { withFileTypes: true })) {
        if (entry.isDirectory()) countRecursive(join(dir, entry.name));
        else if (entry.isFile()) count++;
      }
    } catch {}
  };
  countRecursive(userDir);
  return count;
}

function countHooks(): number {
  const hooksDir = join(CLAUDE_DIR, "hooks");
  if (!existsSync(hooksDir)) return 0;
  let count = 0;
  try {
    for (const entry of readdirSync(hooksDir, { withFileTypes: true })) {
      if (entry.isFile() && entry.name.endsWith(".ts")) count++;
    }
  } catch {}
  return count;
}

function countSessions(): number {
  const historyFile = join(CLAUDE_DIR, "MEMORY", "history.jsonl");
  if (!existsSync(historyFile)) return 0;
  try {
    const content = readFileSync(historyFile, "utf-8");
    return content.split("\n").filter(line => line.trim()).length;
  } catch {
    return 0;
  }
}

function getStats(): SystemStats {
  return {
    name: readDAIdentity(),
    skills: countSkills(),
    userFiles: countUserFiles(),
    hooks: countHooks(),
    sessions: countSessions(),
    model: "Opus 4.5",
  };
}

// ═══════════════════════════════════════════════════════════════════════
// ASCII Art Generation
// ═══════════════════════════════════════════════════════════════════════

function generateColoredArt(name: string): string[] {
  const chars = name.toUpperCase().split("").filter(c => c in LETTERS);
  const rows: string[] = ["", "", "", "", ""];

  for (let charIdx = 0; charIdx < chars.length; charIdx++) {
    const char = chars[charIdx];
    const letterArt = LETTERS[char] || LETTERS[" "];
    const color = LETTER_COLORS[charIdx % LETTER_COLORS.length];

    for (let row = 0; row < 5; row++) {
      rows[row] += `${BOLD}${color}${letterArt[row]}${RESET} `;
    }
  }

  return rows.map(r => r.trimEnd());
}

function colorName(name: string): string {
  let result = "";
  const chars = name.split("");
  for (let i = 0; i < chars.length; i++) {
    result += `${BOLD}${LETTER_COLORS[i % LETTER_COLORS.length]}${chars[i]}${RESET}`;
  }
  return result;
}

// ═══════════════════════════════════════════════════════════════════════
// Banner Modes
// ═══════════════════════════════════════════════════════════════════════

/**
 * NANO mode (<40 chars): Minimal colored status
 * Example: ◆ PAI │ ✓ 42 skills
 */
function createNanoBanner(stats: SystemStats): string {
  const paiColored = `${BOLD}${COLORS.blue}P${RESET}${BOLD}${COLORS.magenta}A${RESET}${BOLD}${COLORS.cyan}I${RESET}`;
  return `${COLORS.blue}${STATUS.diamond}${RESET} ${paiColored} ${COLORS.frame}${STATUS.bar}${RESET} ${COLORS.green}${STATUS.check}${RESET} ${COLORS.text}${stats.skills}${RESET}`;
}

/**
 * MICRO mode (40-59 chars): Compact box with PAI branding
 */
function createMicroBanner(stats: SystemStats): string {
  const paiColored = `${BOLD}${COLORS.blue}P${RESET}${BOLD}${COLORS.magenta}A${RESET}${BOLD}${COLORS.cyan}I${RESET}`;
  const width = 38;
  const inner = width - 2;

  const lines: string[] = [];
  const f = COLORS.frame;
  const t = COLORS.text;
  const g = COLORS.green;
  const s = COLORS.subtext;

  lines.push(`${f}${BOX.topLeft}${BOX.horizontal} ${RESET}${paiColored} ${f}${BOX.horizontal.repeat(inner - 6)}${BOX.topRight}${RESET}`);
  lines.push(`${f}${BOX.vertical}${RESET} ${s}github.com/danielmiessler/pai${RESET}      ${f}${BOX.vertical}${RESET}`);
  lines.push(`${f}${BOX.leftT}${BOX.horizontal.repeat(inner)}${BOX.rightT}${RESET}`);
  lines.push(`${f}${BOX.vertical}${RESET} ${g}${STATUS.check}${RESET} ${t}${stats.skills}${RESET} ${s}skills${RESET}  ${g}${STATUS.circle}${RESET} ${t}${stats.hooks}${RESET} ${s}hooks${RESET}${" ".repeat(inner - 24)}${f}${BOX.vertical}${RESET}`);
  lines.push(`${f}${BOX.bottomLeft}${BOX.horizontal.repeat(inner)}${BOX.bottomRight}${RESET}`);

  return lines.join("\n");
}

/**
 * MINI mode (60-84 chars): Compact box with PAI branding and URL
 */
function createMiniBanner(stats: SystemStats): string {
  const paiColored = `${BOLD}${COLORS.blue}P${RESET}${BOLD}${COLORS.magenta}A${RESET}${BOLD}${COLORS.cyan}I${RESET}`;
  const width = 56;
  const inner = width - 2;

  const f = COLORS.frame;
  const t = COLORS.text;
  const g = COLORS.green;
  const c = COLORS.cyan;
  const s = COLORS.subtext;
  const m = COLORS.magenta;

  const lines: string[] = [];

  // Header with PAI branding
  lines.push(`${f}${BOX.topLeft}${BOX.horizontal} ${RESET}${paiColored} ${s}(Personal AI System)${RESET} ${f}${BOX.horizontal.repeat(inner - 27)}${BOX.topRight}${RESET}`);
  lines.push(`${f}${BOX.vertical}${RESET} ${c}github.com/danielmiessler/pai${RESET}${" ".repeat(inner - 31)}${f}${BOX.vertical}${RESET}`);
  lines.push(`${f}${BOX.leftT}${BOX.horizontal.repeat(inner)}${BOX.rightT}${RESET}`);

  // Stats row 1
  const row1 = ` ${g}${STATUS.check}${RESET} ${s}Core${RESET}    ${c}${STATUS.circle}${RESET} ${m}${stats.skills}${RESET} ${s}skills${RESET}    ${c}${STATUS.circle}${RESET} ${m}${stats.userFiles}${RESET} ${s}files${RESET}`;
  const row1Visible = 6 + 4 + 4 + String(stats.skills).length + 7 + 4 + String(stats.userFiles).length + 6;
  lines.push(`${f}${BOX.vertical}${RESET}${row1}${" ".repeat(inner - row1Visible)}${f}${BOX.vertical}${RESET}`);

  // Stats row 2
  const row2 = ` ${c}${STATUS.circle}${RESET} ${m}${stats.hooks}${RESET} ${s}hooks${RESET}    ${c}${STATUS.circle}${RESET} ${m}${stats.sessions}${RESET} ${s}sessions${RESET}`;
  const row2Visible = 2 + String(stats.hooks).length + 7 + 4 + String(stats.sessions).length + 9;
  lines.push(`${f}${BOX.vertical}${RESET}${row2}${" ".repeat(inner - row2Visible)}${f}${BOX.vertical}${RESET}`);

  lines.push(`${f}${BOX.bottomLeft}${BOX.horizontal.repeat(inner)}${BOX.bottomRight}${RESET}`);

  return lines.join("\n");
}

/**
 * PAI logo using block chars - from session start
 */
function getPaiLogo(): string[] {
  const b = rgb(130, 180, 255);
  const p = rgb(180, 140, 240);
  return [
    `${b}█████${RESET}     `,
    `${b}██${RESET}  ${b}██${RESET}    `,
    `${b}██${RESET}  ${b}██${RESET}    `,
    `${b}█████${RESET}     `,
    `${b}██${RESET} ${p}█${RESET}   ${p}██${RESET}`,
    `${b}██${RESET}  ${p}█${RESET}  ${p}██${RESET}`,
    `${b}██${RESET}   ${p}█${RESET} ${p}██${RESET}`,
    `${b}██${RESET}    ${p}███${RESET}`,
  ];
}

/**
 * NORMAL mode (85+ chars): Clean centered KAI
 */
function createNormalBanner(stats: SystemStats): string {
  const nameArt = generateColoredArt(stats.name);

  const f = COLORS.frame;
  const s = COLORS.subtext;

  const neonCyan = rgb(0, 255, 255);
  const neonPurple = rgb(180, 100, 255);
  const darkTeal = rgb(45, 130, 130);

  const lines: string[] = [];
  const pai = `${BOLD}${neonCyan}P${RESET}${BOLD}${neonPurple}A${RESET}${BOLD}${COLORS.cyan}I${RESET}`;

  lines.push(`${f}╔${"═".repeat(50)}${RESET}`);
  lines.push(`${f}║${RESET} ${neonCyan}◈${RESET} ${pai} ${s}┊${RESET} ${COLORS.text}Personal AI Infrastructure${RESET}`);
  lines.push(`${f}║${RESET} ${s}"Magnifying human capabilities..."${RESET}`);
  lines.push(`${f}║${RESET} ${neonPurple}⟁${RESET} ${darkTeal}github.com/danielmiessler/PAI${RESET}`);
  lines.push(`${f}╠${"═".repeat(50)}${RESET}`);

  for (const row of nameArt) {
    lines.push(`${f}║${RESET} ${row}`);
  }

  lines.push(`${f}╚${"═".repeat(50)}${RESET}`);

  return lines.join("\n");
}

// ═══════════════════════════════════════════════════════════════════════
// Main
// ═══════════════════════════════════════════════════════════════════════

function createBanner(forceMode?: DisplayMode): string {
  const mode = forceMode || getDisplayMode();
  const stats = getStats();

  switch (mode) {
    case "nano":
      return createNanoBanner(stats);
    case "micro":
      return createMicroBanner(stats);
    case "mini":
      return createMiniBanner(stats);
    case "normal":
    default:
      return createNormalBanner(stats);
  }
}

// CLI args: --test (show all modes), --mode=nano|micro|mini|normal
const args = process.argv.slice(2);
const testMode = args.includes("--test");
const modeArg = args.find(a => a.startsWith("--mode="))?.split("=")[1] as DisplayMode | undefined;

try {
  if (testMode) {
    const modes: DisplayMode[] = ["nano", "micro", "mini", "normal"];
    for (const mode of modes) {
      console.log(`\n${"═".repeat(60)}`);
      console.log(`  MODE: ${mode.toUpperCase()}`);
      console.log(`${"═".repeat(60)}`);
      console.log(createBanner(mode));
    }
  } else {
    console.log();
    console.log(createBanner(modeArg));
    console.log();
  }
} catch (e) {
  console.error("Banner error:", e);
}
