'use client';
import { lazy, Suspense, useState, useEffect } from 'react';
import Link from 'next/link';
import {
  Search,
  ArrowUpRight,
  ArrowLeft,
  Download,
  Play,
  Copy,
  Check,
} from 'lucide-react';
import {
  assets,
  assetCounts,
  categoryLabels,
  assetSource,
  getAssetFiles,
  selectFile,
  type AssetFiles,
} from '@/lib/assets';
const Viewer = lazy(() => import('./asset-viewer'));
export function AssetCatalog({ kind, slug }: { kind: string; slug?: string }) {
  const [q, setQ] = useState(''),
    [category, setCategory] = useState('Все'),
    [limit, setLimit] = useState(36),
    [sort, setSort] = useState('curated'),
    [active, setActive] = useState(false),
    [files, setFiles] = useState<AssetFiles | null>(null),
    [error, setError] = useState(''),
    [copied, setCopied] = useState(false);
  const item = assets.find((a) => a.id === slug && a.kind === kind),
    list = assets.filter((a) => a.kind === kind);
  useEffect(() => {
    if (!item) return;
    const c = new AbortController();
    getAssetFiles(item.id, c.signal)
      .then(setFiles)
      .catch((e) => {
        if (!c.signal.aborted) setError(e.message);
      });
    return () => c.abort();
  }, [item]);
  const picks = [
    'pipe_wrench',
    'Camera_01',
    'marble_bust_01',
    'ArmChair_01',
    'brass_goblets',
    'potted_plant_02',
    'ratchet_wrench',
    'sofa_02',
    'combination_wrench',
    'vintage_hand_drill',
    'metal_plate',
    'marble_01',
    'leather_red_02',
    'brown_photostudio_02',
    'lilienstein',
  ];
  const rank = (id: string) => (picks.includes(id) ? picks.indexOf(id) : -1);
  const found = list
    .filter(
      (a) =>
        (category === 'Все' || a.categories.includes(category)) &&
        `${a.name} ${a.tags.join(' ')} ${a.categories.map((c) => categoryLabels[c] || c).join(' ')}`
          .toLowerCase()
          .includes(q.toLowerCase()),
    )
    .sort((a, b) =>
      sort === 'curated' && (rank(a.id) >= 0 || rank(b.id) >= 0)
        ? (rank(a.id) < 0 ? 999 : rank(a.id)) -
          (rank(b.id) < 0 ? 999 : rank(b.id))
        : sort === 'name'
          ? a.name.localeCompare(b.name)
          : sort === 'light'
            ? (a.polycount || Infinity) - (b.polycount || Infinity)
            : b.downloads - a.downloads,
    );
  const categories = [...new Set(list.flatMap((a) => a.categories))].sort(
    (a, b) => a.localeCompare(b),
  );
  return (
    <section className="asset-library">
      <nav className="collection-tabs" aria-label="Коллекции ассетов">
        {[
          ['models', 'Готовые модели'],
          ['pbr', 'PBR-текстуры'],
          ['environments', 'HDRI / свет'],
        ].map(([id, title]) => (
          <Link
            key={id}
            href={'/' + id}
            className={id === kind ? 'selected' : ''}
          >
            {title}
            <span>{assetCounts[id]}</span>
          </Link>
        ))}
        <Link href="/objects">
          Процедурные формы<span>36</span>
        </Link>
      </nav>
      <div className="provider-credit">
        <a href="https://polyhaven.com" target="_blank" rel="noreferrer">
          Powered by Poly Haven <ArrowUpRight size={13} />
        </a>
        <span>Открытые ассеты · CC0 · индекс от 08.09.2026</span>
      </div>
      {item ? (
        <>
          <div className="specimen-detail-head">
            <div>
              <Link href={'/' + kind}>
                <ArrowLeft size={14} />В коллекцию
              </Link>
              <h2>{item.name}</h2>
              <p>
                {item.categories.map((c) => categoryLabels[c] || c).join(' · ')}
              </p>
            </div>
            <a
              className="outline-button"
              href={assetSource(item)}
              target="_blank"
              rel="noreferrer"
            >
              Источник и все форматы
              <ArrowUpRight size={15} />
            </a>
          </div>
          <div className="asset-detail">
            <div className="asset-detail-stage">
              {active && files ? (
                <Suspense fallback={<p>Подготавливаем сцену…</p>}>
                  <Viewer key={item.id} asset={item} files={files} />
                </Suspense>
              ) : (
                <>
                  <img
                    src={item.thumbnail
                      .replace('width=256', 'width=1024')
                      .replace('height=256', 'height=1024')}
                    alt={item.name}
                  />
                  <button
                    className="primary"
                    disabled={!files || !!error}
                    onClick={() => setActive(true)}
                  >
                    <Play size={18} />
                    {error
                      ? 'Ошибка загрузки'
                      : files
                        ? 'Открыть интерактивную сцену'
                        : 'Загружаем параметры…'}
                  </button>
                </>
              )}
            </div>
            <aside className="asset-facts">
              <span className="eyebrow">ASSET RECORD</span>
              <h3>Можно использовать в своём проекте</h3>
              <dl>
                <dt>Автор</dt>
                <dd>{item.author}</dd>
                <dt>Лицензия ассета</dt>
                <dd>
                  <a
                    href="https://creativecommons.org/publicdomain/zero/1.0/"
                    target="_blank"
                    rel="noreferrer"
                  >
                    CC0 / Public domain ↗
                  </a>
                </dd>
                {item.polycount != null && (
                  <>
                    <dt>Полигонов у исходника</dt>
                    <dd>{item.polycount.toLocaleString('ru')}</dd>
                  </>
                )}
                <dt>Текстуры до</dt>
                <dd>
                  {item.resolution
                    ? `${Math.max(...item.resolution)} px`
                    : 'См. источник'}
                </dd>
                <dt>Загрузка сцены</dt>
                <dd>1K по умолчанию · файлы с Poly Haven</dd>
              </dl>
              <p>
                Превью показывает оригинальный ассет. В сцене доступны камера,
                свет и сравнение материалов. Тяжёлые файлы загружаются после
                нажатия.
              </p>
              <button
                className="outline-button"
                onClick={async () => {
                  try {
                    await navigator.clipboard.writeText(
                      `Используй ${item.name}: ${location.href}. Каталог: ${location.origin}/assets/registry.json. Файлы: https://api.polyhaven.com/files/${item.id}. Лицензия CC0. Исходник viewer: ${location.origin}/source/components/asset-viewer.tsx. Сохрани glTF-зависимости из include, используй 1K для веба.`,
                    );
                    setCopied(true);
                  } catch {}
                }}
              >
                {copied ? <Check size={15} /> : <Copy size={15} />}Промпт для
                агента
              </button>
              <a className="subtle" href="/source/components/asset-viewer.tsx">
                Исходник просмотрщика ↗
              </a>
            </aside>
          </div>
          {error && (
            <p role="status">
              {error}{' '}
              <button
                className="subtle"
                onClick={() => {
                  setError('');
                  getAssetFiles(item.id)
                    .then(setFiles)
                    .catch((e) => setError(e.message));
                }}
              >
                Повторить
              </button>
            </p>
          )}
          {files && (
            <div className="asset-downloads">
              <h3>Файлы оригинала</h3>
              <p>
                Выбери разрешение и формат. Для glTF нужны также связанные
                текстуры и .bin: просмотрщик умеет скачивать их одним ZIP.
              </p>
              <div>
                {Object.entries(files)
                  .filter(([k]) =>
                    [
                      'gltf',
                      'blend',
                      'hdri',
                      'Diffuse',
                      'diff',
                      'nor_gl',
                      'Rough',
                      'rough',
                      'Metal',
                      'metal',
                      'Displacement',
                      'disp',
                      'AO',
                      'arm',
                    ].includes(k),
                  )
                  .map(([key, versions]) => (
                    <div key={key}>
                      <b>{key}</b>
                      {Object.keys(versions)
                        .filter((v) => ['1k', '2k', '4k'].includes(v))
                        .map((res) => {
                          const f = selectFile(files, [key], res, [
                            'gltf',
                            'blend',
                            'hdr',
                            'exr',
                            'jpg',
                            'png',
                          ]);
                          return f ? (
                            <a
                              key={res}
                              href={f.url}
                              target="_blank"
                              rel="noreferrer"
                            >
                              {res}
                              <small>{(f.size / 1e6).toFixed(1)} MB</small>
                              <Download size={13} />
                            </a>
                          ) : null;
                        })}
                    </div>
                  ))}
              </div>
            </div>
          )}
        </>
      ) : (
        <>
          <div className="collection-tools">
            <label className="collection-search">
              <Search size={17} />
              <input
                value={q}
                onChange={(e) => {
                  setQ(e.target.value);
                  setLimit(36);
                }}
                placeholder="Поиск: wood, металл, chair, камень…"
                aria-label="Поиск ассетов"
              />
            </label>
            <span>{found.length} ассетов</span>
            <a href="/assets/registry.json" download>
              JSON <Download size={15} />
            </a>
          </div>
          <div className="asset-selects">
            <label>
              Категория
              <select
                value={category}
                onChange={(e) => {
                  setCategory(e.target.value);
                  setLimit(36);
                }}
              >
                <option value="Все">Все категории</option>
                {categories.map((c) => (
                  <option key={c} value={c}>
                    {categoryLabels[c] || c}
                  </option>
                ))}
              </select>
            </label>
            <label>
              Порядок
              <select value={sort} onChange={(e) => setSort(e.target.value)}>
                <option value="curated">Выбор редакции</option>
                <option value="popular">Популярные у источника</option>
                <option value="name">По названию</option>
                {kind === 'models' && (
                  <option value="light">Меньше полигонов</option>
                )}
              </select>
            </label>
          </div>
          <div className="asset-grid">
            {found.slice(0, limit).map((a, i) => (
              <article key={a.id}>
                <Link
                  className={'asset-poster poster-' + kind}
                  href={`/${kind}/${a.id}`}
                >
                  <img
                    src={a.thumbnail}
                    alt={a.name}
                    loading="lazy"
                    decoding="async"
                  />
                  <span className="asset-view-label">
                    <Play size={14} />
                    Открыть сцену
                  </span>
                </Link>
                <div className="asset-card-title">
                  <span>{String(i + 1).padStart(3, '0')}</span>
                  <Link href={`/${kind}/${a.id}`}>
                    <h3>{a.name}</h3>
                    <p>
                      {a.categories
                        .slice(0, 2)
                        .map((c) => categoryLabels[c] || c)
                        .join(' / ')}
                    </p>
                  </Link>
                  <ArrowUpRight size={17} />
                </div>
                <div className="asset-card-credit">
                  <span>{a.author}</span>
                  <b>CC0</b>
                </div>
              </article>
            ))}
          </div>
          {found.length === 0 && (
            <div className="empty">
              <h3>Ничего не нашлось</h3>
              <button
                className="outline-button"
                onClick={() => {
                  setQ('');
                  setCategory('Все');
                }}
              >
                Сбросить поиск
              </button>
            </div>
          )}
          {limit < found.length && (
            <button
              className="outline-button asset-load"
              onClick={() => setLimit((v) => v + 36)}
            >
              Показать ещё 36{' '}
              <span>
                {Math.min(limit, found.length)} / {found.length}
              </span>
            </button>
          )}
        </>
      )}
    </section>
  );
}
