import { useState } from 'react';

interface JsonViewerProps {
  data: unknown;
  collapsed?: boolean;
}

export function JsonViewer({ data, collapsed = false }: JsonViewerProps) {
  return (
    <pre className="text-xs font-mono overflow-auto p-3 bg-surface rounded-md border border-border">
      <JsonNode value={data} collapsed={collapsed} depth={0} />
    </pre>
  );
}

function JsonNode({ value, collapsed, depth }: { value: unknown; collapsed: boolean; depth: number }) {
  if (value === null) return <span className="text-text-muted">null</span>;
  if (typeof value === 'boolean') return <span className="text-accent-violet">{String(value)}</span>;
  if (typeof value === 'number') return <span className="text-accent-amber">{String(value)}</span>;
  if (typeof value === 'string') return <span className="text-accent-green">&quot;{value}&quot;</span>;

  if (Array.isArray(value)) {
    return <CollapsibleNode collapsed={collapsed} depth={depth} brackets={['[', ']']} items={value} isArray />;
  }

  if (typeof value === 'object') {
    const entries = Object.entries(value as Record<string, unknown>);
    return <CollapsibleNode collapsed={collapsed} depth={depth} brackets={['{', '}']} items={entries} isArray={false} />;
  }

  return <span className="text-text-primary">{String(value)}</span>;
}

function CollapsibleNode({
  collapsed: initialCollapsed,
  depth,
  brackets,
  items,
  isArray,
}: {
  collapsed: boolean;
  depth: number;
  brackets: [string, string];
  items: unknown[] | [string, unknown][];
  isArray: boolean;
}) {
  const [isCollapsed, setIsCollapsed] = useState(initialCollapsed);
  const indent = '  '.repeat(depth + 1);
  const closingIndent = '  '.repeat(depth);

  if (items.length === 0) {
    return <span>{brackets[0]}{brackets[1]}</span>;
  }

  if (isCollapsed) {
    return (
      <span className="cursor-pointer hover:opacity-70" onClick={() => setIsCollapsed(false)}>
        {brackets[0]} <span className="text-text-muted">... {items.length} items</span> {brackets[1]}
      </span>
    );
  }

  return (
    <span>
      <span className="cursor-pointer hover:opacity-70" onClick={() => setIsCollapsed(true)}>
        {brackets[0]}
      </span>
      {'\n'}
      {(items as unknown[]).map((item, i) => {
        const isLast = i === items.length - 1;
        if (isArray) {
          return (
            <span key={i}>
              {indent}
              <JsonNode value={item} collapsed={depth > 1} depth={depth + 1} />
              {!isLast && ','}{'\n'}
            </span>
          );
        }
        const [key, val] = item as [string, unknown];
        return (
          <span key={key}>
            {indent}
            <span className="text-accent-blue">&quot;{key}&quot;</span>
            <span className="text-text-secondary">: </span>
            <JsonNode value={val} collapsed={depth > 1} depth={depth + 1} />
            {!isLast && ','}{'\n'}
          </span>
        );
      })}
      {closingIndent}{brackets[1]}
    </span>
  );
}
