import {
  ArrowRight,
  CheckCircle2,
  Code2,
  FileText,
  FlaskConical,
  GitBranch,
  Package,
  Search,
  ShieldCheck,
  SquareTerminal,
  Wrench,
  type LucideIcon,
} from 'lucide-react';
import React from 'react';
import softwareCatalog from './software-catalog.json';

const CATEGORY_ICONS: Readonly<Record<string, LucideIcon>> = Object.freeze({
  'Languages & runtimes': Code2,
  'Compilers & build tools': Wrench,
  'Scientific Python': FlaskConical,
  'LaTeX & documents': FileText,
  'Git & project tools': GitBranch,
  'Linux & shell tools': SquareTerminal,
});

const CATEGORY_ORDER = [
  'Languages & runtimes',
  'Compilers & build tools',
  'Scientific Python',
  'LaTeX & documents',
  'Git & project tools',
  'Linux & shell tools',
] as const;

type EnvironmentName = 'terminal' | 'compile';
type EnvironmentFilter = 'all' | EnvironmentName;
type CatalogEntry = {
  id: string;
  name: string;
  command: string;
  category: string;
  description: string;
  environments: readonly EnvironmentName[];
  version?: string;
  versionCommand?: string;
};
type SoftwareCatalog = {
  image: string;
  highlights: readonly string[];
  networkNote: string;
  persistenceNote: string;
  environments: Readonly<Record<EnvironmentName, { label: string; description: string }>>;
  entries: readonly CatalogEntry[];
};
const CATALOG = softwareCatalog as SoftwareCatalog;

function environmentLabel(value: EnvironmentName) {
  return value === 'terminal' ? 'Terminal' : 'Compile';
}

export function SoftwareListPage() {
  const [query, setQuery] = React.useState('');
  const [environment, setEnvironment] = React.useState<EnvironmentFilter>('all');
  const [category, setCategory] = React.useState('all');
  const normalized = query.trim().toLowerCase();
  const categories = React.useMemo(() => CATEGORY_ORDER.filter((name) => CATALOG.entries.some((entry) => entry.category === name)), []);
  const visible = React.useMemo(() => CATALOG.entries.filter((entry) => {
    if (environment !== 'all' && !entry.environments.includes(environment)) return false;
    if (category !== 'all' && entry.category !== category) return false;
    if (!normalized) return true;
    return [entry.name, entry.command, entry.category, entry.description, entry.version || '', entry.versionCommand || '']
      .join(' ')
      .toLowerCase()
      .includes(normalized);
  }), [category, environment, normalized]);
  const grouped = React.useMemo(() => categories
    .map((name) => [name, visible.filter((entry) => entry.category === name)] as const)
    .filter(([, entries]) => entries.length > 0), [categories, visible]);

  return <article className="interactive-software-page">
    <header className="interactive-page-container interactive-software-hero">
      <span className="interactive-eyebrow">Runtime software</span>
      <h1>Software included with Learnitive</h1>
      <p>Explore the certified languages, compilers, scientific libraries, LaTeX tools and Linux utilities built into the unified Learnitive development image.</p>
      <div className="interactive-software-image-chip"><Package className="size-4" aria-hidden="true"/><span>Current staging image</span><code>{CATALOG.image}</code></div>
    </header>

    <section className="interactive-page-container interactive-software-environments" aria-labelledby="software-environments-title">
      <div className="interactive-section-heading interactive-centered-heading"><span className="interactive-eyebrow">One certified toolchain</span><h2 id="software-environments-title">Compile and terminal use the same base image</h2><p>The current staging runtime deliberately uses one unified development image so important commands are consistent between server-side builds and interactive terminal sessions.</p></div>
      <div className="interactive-software-environment-grid">
        <article><span className="interactive-software-environment-icon"><SquareTerminal className="size-5" aria-hidden="true"/></span><div><h3>{CATALOG.environments.terminal.label}</h3><p>{CATALOG.environments.terminal.description}</p></div></article>
        <article><span className="interactive-software-environment-icon"><Code2 className="size-5" aria-hidden="true"/></span><div><h3>{CATALOG.environments.compile.label}</h3><p>{CATALOG.environments.compile.description}</p></div></article>
      </div>
      <div className="interactive-software-highlights" aria-label="Highlighted runtime software">{CATALOG.highlights.map((item) => <span key={item}><CheckCircle2 className="size-4" aria-hidden="true"/>{item}</span>)}</div>
    </section>

    <section className="interactive-page-container interactive-software-catalog" aria-labelledby="software-catalog-title">
      <div className="interactive-section-heading interactive-centered-heading"><span className="interactive-eyebrow">Package catalog</span><h2 id="software-catalog-title">Important software and commands</h2><p>Search by tool, command or workflow. Versions without a fixed number are supplied by the certified image build; use the shown command to inspect the exact runtime version.</p></div>
      <div className="interactive-software-controls">
        <label className="interactive-software-search"><span className="sr-only">Search software, commands or packages</span><Search className="size-4" aria-hidden="true"/><input type="search" value={query} onChange={(event) => setQuery(event.currentTarget.value)} placeholder="Search software, commands or packages…"/></label>
        <div className="interactive-software-filter-row" aria-label="Environment filter">
          {([['all','All software'],['terminal','Interactive Terminal'],['compile','Compile & Run']] as const).map(([value,label]) => <button key={value} type="button" data-active={environment===value?'true':undefined} onClick={() => setEnvironment(value)}>{label}</button>)}
        </div>
        <div className="interactive-software-filter-row interactive-software-category-row" aria-label="Category filter">
          <button type="button" data-active={category==='all'?'true':undefined} onClick={() => setCategory('all')}>All categories</button>
          {categories.map((name) => <button key={name} type="button" data-active={category===name?'true':undefined} onClick={() => setCategory(name)}>{name}</button>)}
        </div>
      </div>

      <div className="interactive-software-groups">
        {grouped.map(([name, entries]) => {
          const Icon = CATEGORY_ICONS[name] || Package;
          return <section key={name} className="interactive-software-group" aria-labelledby={`software-${name.replace(/[^a-z0-9]+/giu,'-').toLowerCase()}`}>
            <header><span className="interactive-software-group-icon"><Icon className="size-5" aria-hidden="true"/></span><div><h3 id={`software-${name.replace(/[^a-z0-9]+/giu,'-').toLowerCase()}`}>{name}</h3><small>{entries.length} {entries.length===1?'item':'items'}</small></div></header>
            <div className="interactive-software-grid">{entries.map((entry) => <SoftwareCard key={entry.id} entry={entry}/>)}</div>
          </section>;
        })}
        {visible.length === 0 ? <div className="interactive-software-empty"><Search className="size-5"/><strong>No matching software</strong><p>Try another command, package name, category or environment filter.</p></div> : null}
      </div>
    </section>

    <section className="interactive-page-container interactive-software-notes" aria-labelledby="software-runtime-notes-title">
      <div className="interactive-section-heading"><span className="interactive-eyebrow">Runtime notes</span><h2 id="software-runtime-notes-title">Included software is separate from network and persistence policy</h2></div>
      <div className="interactive-software-note-grid">
        <article><ShieldCheck className="size-5" aria-hidden="true"/><h3>Controlled networking</h3><p>{CATALOG.networkNote}</p></article>
        <article><Package className="size-5" aria-hidden="true"/><h3>Project dependencies</h3><p>{CATALOG.persistenceNote}</p></article>
      </div>
      <div className="interactive-about-links"><a className="interactive-text-link" href="/docs/runtime-software">How runtime software works <ArrowRight className="size-4" aria-hidden="true"/></a><a className="interactive-text-link" href="/use-cases">Explore use cases <ArrowRight className="size-4" aria-hidden="true"/></a></div>
    </section>

    <section className="interactive-page-container interactive-final-cta"><h2>Ready to use the toolchain?</h2><p>Open a project, start the terminal, or choose a ready-to-run template.</p><div className="interactive-hero-actions"><a className="interactive-button interactive-button-primary" href="/projects">Open Projects <ArrowRight className="size-4" aria-hidden="true"/></a><a className="interactive-button interactive-button-secondary" href="/templates">Browse Templates</a></div></section>
  </article>;
}

function SoftwareCard({ entry }: { entry: CatalogEntry }) {
  return <article className="interactive-software-card">
    <div className="interactive-software-card-title"><div><h4>{entry.name}</h4>{entry.version ? <span>v{entry.version}</span> : null}</div><code>{entry.command}</code></div>
    <p>{entry.description}</p>
    <div className="interactive-software-card-badges">{entry.environments.map((item) => <span key={item}>{environmentLabel(item)}</span>)}</div>
    {entry.versionCommand ? <div className="interactive-software-version-command"><span>Check version</span><code>{entry.versionCommand}</code></div> : null}
  </article>;
}
