// app-shell.jsx — Shared Main App layout: dock + sidebar + workspace
// Liquid Glass floating dock on the left, secondary sidebar, main canvas area.

const APP_W = 1280;
const APP_H = 800;

// ─────────────────────────────────────────────────────────────
// Floating Dock (left edge) — primary nav between modes
// ─────────────────────────────────────────────────────────────
function AppDock({ active = 'chat', dark, style = {}, update }) {
  const t = dark ? G.d : G.l;
  const items = [
    { id: 'chat', icon: 'chat', label: 'Chat' },
    { id: 'workflow', icon: 'workflow', label: 'Workflows' },
    { id: 'code', icon: 'code', label: 'Develop' },
  ];
  const stores = [
    { id: 'skills', icon: 'skills', label: 'Skills' },
    { id: 'mcp', icon: 'plug', label: 'MCP' },
    { id: 'workflows-store', icon: 'box', label: 'Workflows' },
  ];
  const updateActive = active === 'update';
  return (
    <div style={{
      position: 'absolute', top: 50, bottom: 14, left: 14, width: 56,
      display: 'flex', flexDirection: 'column', zIndex: 5,
      ...style,
    }}>
      <Glass radius={28} dark={dark} style={{ flex: 1 }}>
        <div style={{ padding: 8, display: 'flex', flexDirection: 'column', gap: 4, height: '100%' }}>
          {/* Logo */}
          <div style={{ width: 40, height: 40, display: 'flex', alignItems: 'center', justifyContent: 'center', borderRadius: 12, marginBottom: 4 }}>
            <GhastLogo size={26} color={t.fg} />
          </div>
          <Divider style={{ margin: '4px 8px', width: 'auto', background: t.border }} />
          {items.map((it) => {
            const isActive = it.id === active;
            return (
              <div key={it.id} title={it.label} style={{
                width: 40, height: 40, borderRadius: 12,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                background: isActive ? t.fg : 'transparent',
                color: isActive ? t.bg : t.fg2,
                cursor: 'pointer',
              }}>
                <Icon name={it.icon} size={18} />
              </div>
            );
          })}
          <div style={{ flex: 1 }} />
          {/* Update indicator — surfaces only when update?.available === true */}
          {update && update.available && (
            <>
              <Divider style={{ margin: '4px 8px', width: 'auto', background: t.border }} />
              <div title={update.title || `Ghast ${update.version || ''} available`} style={{
                position: 'relative',
                width: 40, height: 40, borderRadius: 12,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                background: updateActive ? t.fg : 'transparent',
                color:      updateActive ? t.bg : t.fg2,
                cursor: 'pointer',
              }}>
                <Icon name="arrow-down-to-line" size={18} />
                {/* Red dot — semantic update notification */}
                <span style={{
                  position: 'absolute', top: 7, right: 7,
                  width: 8, height: 8, borderRadius: 999,
                  background: '#ff5f57', boxShadow: `0 0 0 2px ${dark ? 'rgba(20,20,20,0.92)' : 'rgba(255,255,255,0.92)'}`,
                }} />
              </div>
            </>
          )}
          <Divider style={{ margin: '4px 8px', width: 'auto', background: t.border }} />
          {stores.map((it) => {
            const isActive = it.id === active;
            return (
              <div key={it.id} title={it.label} style={{
                width: 40, height: 40, borderRadius: 12,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                background: isActive ? t.fg : 'transparent',
                color: isActive ? t.bg : t.fg2,
                cursor: 'pointer',
              }}>
                <Icon name={it.icon} size={18} />
              </div>
            );
          })}
          <div title="Settings" style={{
            width: 40, height: 40, borderRadius: 12,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            color: active === 'settings' ? t.bg : t.fg2,
            background: active === 'settings' ? t.fg : 'transparent',
            cursor: 'pointer',
          }}>
            <Icon name="settings" size={18} />
          </div>
        </div>
      </Glass>
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Secondary sidebar (per-section)
// ─────────────────────────────────────────────────────────────
function AppSidebar({ title, search, sections = [], onNew, dark, footer, header, width = 250 }) {
  const t = dark ? G.d : G.l;
  return (
    <div style={{
      width, height: '100%', flexShrink: 0,
      borderRight: `0.5px solid ${t.border}`,
      display: 'flex', flexDirection: 'column',
      paddingTop: 36, // for traffic lights
    }}>
      {/* Header */}
      <div style={{ padding: '10px 16px 8px', display: 'flex', alignItems: 'center', justifyContent: 'space-between' }}>
        <div style={{ fontSize: 13, fontWeight: 600, letterSpacing: -0.1 }}>{title}</div>
        {onNew && (
          <button style={{
            width: 24, height: 24, borderRadius: 6, background: 'transparent',
            border: 'none', color: t.fg2, cursor: 'pointer',
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}><Icon name="plus" size={14} /></button>
        )}
      </div>
      {search && (
        <div style={{ padding: '4px 12px 8px' }}>
          <div style={{
            height: 28, padding: '0 10px',
            display: 'flex', alignItems: 'center', gap: 6,
            background: t.surface2, border: `1px solid ${t.border2}`,
            borderRadius: 8,
          }}>
            <Icon name="search" size={13} color={t.fg3} />
            <span style={{ fontSize: 12, color: t.fg3, flex: 1 }}>{typeof search === 'string' ? search : 'Search'}</span>
            <Kbd>⌘K</Kbd>
          </div>
        </div>
      )}
      {header}
      <div className="gh-scroll" style={{ flex: 1, overflow: 'auto', padding: '4px 8px 8px' }}>
        {sections.map((sec, si) => (
          <div key={si} style={{ marginBottom: 14 }}>
            {sec.title && (
              <div style={{ padding: '8px 8px 4px', fontSize: 10, fontWeight: 600, color: t.fg3, letterSpacing: 1, textTransform: 'uppercase' }}>
                {sec.title}
              </div>
            )}
            {sec.items.map((it, ii) => {
              const isActive = it.active;
              return (
                <div key={ii} style={{
                  padding: '7px 10px', borderRadius: 8,
                  display: 'flex', alignItems: 'center', gap: 8,
                  background: isActive ? t.surface2 : 'transparent',
                  cursor: 'pointer',
                  marginBottom: 1,
                }}>
                  {it.icon && <Icon name={it.icon} size={14} color={isActive ? t.fg : t.fg2} />}
                  {it.dot && <div style={{ width: 6, height: 6, borderRadius: 3, background: it.dot === 'on' ? t.fg : t.fg4, flexShrink: 0 }} />}
                  <span style={{ flex: 1, fontSize: 12.5, color: isActive ? t.fg : t.fg2, fontWeight: isActive ? 500 : 400, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
                    {it.label}
                  </span>
                  {it.meta && <span style={{ fontSize: 10, color: t.fg3, fontFamily: G.mono }}>{it.meta}</span>}
                  {it.badge && <Tag>{it.badge}</Tag>}
                </div>
              );
            })}
          </div>
        ))}
      </div>
      {footer && <div style={{ borderTop: `0.5px solid ${t.border}`, padding: 12 }}>{footer}</div>}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// Top toolbar (within the workspace area, right of dock)
// ─────────────────────────────────────────────────────────────
function AppTopBar({ breadcrumbs = [], right, dark }) {
  const t = dark ? G.d : G.l;
  return (
    <div style={{
      height: 44, flexShrink: 0,
      display: 'flex', alignItems: 'center', gap: 10,
      padding: '0 16px',
      borderBottom: `0.5px solid ${t.border}`,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 6, flex: 1 }}>
        {breadcrumbs.map((b, i) => (
          <React.Fragment key={i}>
            {i > 0 && <Icon name="chevronRight" size={12} color={t.fg4} />}
            <span style={{ fontSize: 12.5, fontWeight: i === breadcrumbs.length - 1 ? 500 : 400, color: i === breadcrumbs.length - 1 ? t.fg : t.fg2 }}>
              {b}
            </span>
          </React.Fragment>
        ))}
      </div>
      {right}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// AppShell — composes window + dock + content
// ─────────────────────────────────────────────────────────────
function AppShell({ dark, active, sidebar, topBar, children, bgTone, update }) {
  const t = dark ? G.d : G.l;
  return (
    <Theme dark={dark}>
      <GhastWindow dark={dark} style={{ height: APP_H, background: bgTone || t.bg }}>
        {/* Traffic lights */}
        <div style={{ position: 'absolute', top: 16, left: 18, zIndex: 20 }}>
          <TrafficLights />
        </div>
        <AppDock active={active} dark={dark} update={update} />
        <div style={{ width: '100%', height: '100%', paddingLeft: 84, display: 'flex' }}>
          {sidebar}
          <div style={{ flex: 1, display: 'flex', flexDirection: 'column', minWidth: 0 }}>
            {topBar}
            <div style={{ flex: 1, minHeight: 0, position: 'relative' }}>{children}</div>
          </div>
        </div>
      </GhastWindow>
    </Theme>
  );
}

// ─────────────────────────────────────────────────────────────
// Composer (chat input bar, Liquid Glass)
// ─────────────────────────────────────────────────────────────
// Permission modes — controls whether tool calls and edits prompt before
// running. Mirrors the agent runtime contract; UI surface lets the user
// override per-thread or per-message. Inspired by the Claude Code "edit
// mode" and "bypass permissions" affordances.
const PERMISSION_MODES = {
  confirm: { icon: 'lock',   short: 'Confirm',  label: 'Confirm before tools',  desc: 'Ask before each tool call.' },
  auto:    { icon: 'zap',    short: 'Auto',     label: 'Auto-review',           desc: 'Apply edits and run safe tools without prompting.' },
  plan:    { icon: 'eye',    short: 'Plan',     label: 'Plan only',             desc: 'Sketch the steps. Don\'t run anything.' },
  full:    { icon: 'warn',   short: 'Full',     label: 'Full access',           desc: 'Skip every confirmation. High risk.' },
  bypass:  { icon: 'warn',   short: 'Bypass',   label: 'Bypass permissions',    desc: 'Skip every confirmation. High risk.' },
};

// Composer — main chat input. `compact={true}` keeps the same information
// density (model, permission, context, file chip) but switches text affordances
// to icon-only so it stays usable in narrow side panels (320px+).
function Composer({
  value = '',
  placeholder = 'Ask, build, or run...',
  dark,
  attached = [],
  thinking = false,
  large = false,
  compact = false,
  // Status surface
  model = 'Ghast 2 Pro',
  contextFile = null,         // e.g. 'auth.ts' — current file in scope
  contextUsed = 87,           // k tokens used
  contextLimit = 200,         // k tokens cap
  permissionMode = 'confirm', // 'confirm' | 'auto' | 'plan' | 'bypass'
  skillCount = 3,
}) {
  const t = dark ? G.d : G.l;
  // Composer hugs the chat column edge — small horizontal padding so the
  // input frame visibly anchors to the message column rather than floating
  // far inset from it.
  const padX = compact ? 10 : 16;
  const padBottom = compact ? 10 : 16;
  const usagePct = Math.max(0, Math.min(1, contextUsed / contextLimit));
  const contextHot = usagePct >= 0.8;
  const mode = PERMISSION_MODES[permissionMode] || PERMISSION_MODES.confirm;

  // Tag base style used across the toolbar.
  const tagBase = {
    height: compact ? 22 : 24,
    padding: compact ? '0 7px' : '0 8px',
    background: 'transparent', border: `1px solid ${t.border}`,
    borderRadius: 999, gap: 4,
    display: 'inline-flex', alignItems: 'center',
    fontSize: compact ? 10.5 : 11, fontWeight: 500, color: t.fg2,
    cursor: 'pointer', whiteSpace: 'nowrap', flexShrink: 0,
  };
  const iconBtn = (extraStyle = {}) => ({
    width: compact ? 26 : 30, height: compact ? 26 : 30, borderRadius: 8,
    background: 'transparent', border: 'none', color: t.fg2, cursor: 'pointer',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    flexShrink: 0, ...extraStyle,
  });

  return (
    <div style={{ padding: `0 ${padX}px ${padBottom}px`, flexShrink: 0, minWidth: 0 }}>
      <Glass radius={compact ? 14 : 20} dark={dark} style={{ background: 'transparent' }}>
        <div style={{
          padding: compact ? '8px 10px' : '14px 14px 10px',
          display: 'flex', flexDirection: 'column', gap: compact ? 6 : 10,
          minWidth: 0,
        }}>
          {/* Attachment / context chips row (above input) */}
          {(attached.length > 0 || contextFile) && (
            <div style={{ display: 'flex', gap: 6, flexWrap: 'wrap', alignItems: 'center' }}>
              {contextFile && (
                <span style={{
                  height: compact ? 22 : 24, padding: '0 8px 0 6px',
                  background: t.surface2, border: `1px solid ${t.border}`,
                  borderRadius: 999, gap: 5,
                  display: 'inline-flex', alignItems: 'center',
                  fontSize: 11, color: t.fg2, fontFamily: G.mono,
                }}>
                  <Icon name="file" size={11} color={t.fg2} />
                  {contextFile}
                </span>
              )}
              {attached.map((a, i) => (
                <Tag key={i} variant="default" style={{ height: compact ? 22 : 24, padding: '0 8px 0 6px', gap: 6, fontSize: 11 }}>
                  <Icon name={a.icon || 'file'} size={11} color={t.fg2} />
                  {a.label}
                  <Icon name="close" size={10} color={t.fg3} style={{ marginLeft: 2 }} />
                </Tag>
              ))}
            </div>
          )}

          {/* Input area */}
          <div style={{
            minHeight: large ? 60 : (compact ? 24 : 28),
            fontSize: large ? 16 : (compact ? 13 : 14), color: value ? t.fg : t.fg3,
            lineHeight: 1.5, padding: '4px 4px',
            whiteSpace: 'pre-wrap', wordBreak: 'break-word', overflow: 'hidden',
          }}>
            {value || placeholder}
            {value && <span style={{ display: 'inline-block', width: 1, height: 16, background: t.fg, marginLeft: 1, animation: 'gh-blink 1s infinite', verticalAlign: '-3px' }} />}
          </div>

          {/* Toolbar — icons left + chips right + send */}
          <div style={{ display: 'flex', alignItems: 'center', gap: compact ? 4 : 6, flexWrap: 'nowrap', minWidth: 0 }}>
            <button title="Attach" style={iconBtn()}><Icon name="paperclip" size={compact ? 13 : 15} /></button>
            <button title="Slash commands" style={iconBtn()}><Icon name="cmd" size={compact ? 13 : 15} /></button>
            {!compact && (
              <button title="Insert image" style={iconBtn()}><Icon name="image" size={15} /></button>
            )}
            <button title="Voice" style={iconBtn()}><Icon name="mic" size={compact ? 13 : 15} /></button>

            <div style={{ flex: 1, minWidth: 4 }} />

            {/* Skills chip — hide in compact for space, shown via footer instead */}
            {!compact && skillCount > 0 && (
              <span title={`${skillCount} skills active`} style={tagBase}>
                <Icon name="zap" size={11} color={t.fg2} />
                {skillCount}
              </span>
            )}

            {/* Permission mode chip — visible in both modes; compact uses short label */}
            <span title={`${mode.label} · ${mode.desc}`} style={tagBase}>
              <Icon name={mode.icon} size={11} color={(permissionMode === 'bypass' || permissionMode === 'full') ? '#a16207' : t.fg2} />
              {compact ? mode.short : mode.label}
              <Icon name="chevronDown" size={10} color={t.fg3} />
            </span>

            {/* Model chip — compact uses short pill */}
            <span title={model} style={tagBase}>
              <Icon name="sparkle" size={11} color={t.fg2} />
              {compact ? model.replace(/^Ghast\s+/, '').replace(/\s+/g, '·') : model}
              <Icon name="chevronDown" size={10} color={t.fg3} />
            </span>

            {/* Context-usage ring — sits between the model chip and Send so
                "what model + what permission" reads as a single cluster, and
                the ring tooltip surfaces the exact token math on hover. */}
            <ContextRing
              size={compact ? 14 : 16}
              value={usagePct}
              hot={contextHot}
              tooltip={`Context ${formatTokens(contextUsed)} / ${formatTokens(contextLimit)} (${Math.round(usagePct * 100)}%) · ${mode.short}${permissionMode === 'plan' ? ' · plan only' : ''}`}
              color={t.fg2}
              trackColor={t.border}
            />

            {/* Send / Stop */}
            {thinking ? (
              <Button variant="secondary" size="sm" icon={<Icon name="stop" size={11} />}>Stop</Button>
            ) : (
              <button title="Send (↵)" style={{
                width: compact ? 28 : 32, height: compact ? 28 : 32, borderRadius: compact ? 14 : 16,
                background: value ? t.fg : t.surface2, color: value ? t.bg : t.fg3,
                border: value ? 'none' : `1px solid ${t.border}`,
                cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center',
                flexShrink: 0, marginLeft: 2,
              }}><Icon name="arrowUp" size={compact ? 14 : 16} color={value ? t.bg : t.fg3} /></button>
            )}
          </div>
        </div>
      </Glass>
    </div>
  );
}

// Compact "k" / "M" formatter used by the context ring tooltip.
function formatTokens(k) {
  if (k >= 1000) {
    const m = k / 1000;
    return `${m.toFixed(m < 10 ? 1 : 0)}M`;
  }
  return `${k}k`;
}

// Circular progress used as the context-usage indicator. Default is a thin
// 2px ring; hot state (>80% used) flips the stroke to amber.
function ContextRing({ size = 16, value = 0, hot = false, tooltip, color = '#888', trackColor = 'rgba(0,0,0,0.1)' }) {
  const stroke = Math.max(1.5, size * 0.14);
  const r = (size - stroke) / 2;
  const c = size / 2;
  const circumference = 2 * Math.PI * r;
  const offset = circumference * (1 - Math.max(0, Math.min(1, value)));
  const ringColor = hot ? '#febc2e' : color;
  return (
    <span className="gh-tip" style={{ display: 'inline-flex', alignItems: 'center' }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`} style={{ display: 'block' }}>
        <circle cx={c} cy={c} r={r} fill="none" stroke={trackColor} strokeWidth={stroke} />
        <circle
          cx={c} cy={c} r={r} fill="none"
          stroke={ringColor}
          strokeWidth={stroke}
          strokeDasharray={circumference}
          strokeDashoffset={offset}
          strokeLinecap="round"
          transform={`rotate(-90 ${c} ${c})`}
          style={{ transition: 'stroke-dashoffset .3s ease' }}
        />
      </svg>
      {tooltip && <span className="gh-tip-bubble">{tooltip}</span>}
    </span>
  );
}

Object.assign(window, { AppDock, AppSidebar, AppTopBar, AppShell, Composer, APP_W, APP_H });
