// ============================================================
// Catálogo de libros: servidor de solo lectura y demo local explícita
// ============================================================
const catalogValue = (value) => value === null || value === undefined || value === ''
  ? 'No especificado'
  : value;

const catalogLabel = (catalog, value) => value
  ? (catalog[value] || value)
  : 'No especificado';

const CatalogBadge = ({ value, catalog }) => (
  <span className="badge" style={{ background: 'var(--surface-2)', color: 'var(--text-2)', padding: '4px 8px' }}>
    {catalogLabel(catalog, value)}
  </span>
);

const ServerBookDetail = ({ bookId, onClose, onSessionExpired }) => {
  const [state, setState] = useState('loading');
  const [book, setBook] = useState(null);
  const [message, setMessage] = useState('');
  const [retryToken, setRetryToken] = useState(0);
  const requestRef = useRef(0);

  useEffect(() => {
    if (!bookId) return undefined;
    const controller = new AbortController();
    const requestId = ++requestRef.current;
    setState('loading');
    setMessage('');

    window.booksService.getBookById(bookId, { signal: controller.signal })
      .then((loadedBook) => {
        if (requestId !== requestRef.current || controller.signal.aborted) return;
        setBook(loadedBook);
        setState(loadedBook ? 'loaded' : 'error');
        if (!loadedBook) setMessage('No fue posible interpretar los datos del libro.');
      })
      .catch((error) => {
        if (controller.signal.aborted || requestId !== requestRef.current) return;
        if (error?.status === 401) {
          onClose();
          onSessionExpired();
          return;
        }
        setBook(null);
        setState(error?.status === 0 || error?.status >= 500 ? 'unavailable' : 'error');
        setMessage(
          error?.status === 403 ? 'No tienes permiso para consultar este libro.' :
          error?.status === 404 ? 'El libro solicitado ya no está disponible.' :
          'No fue posible cargar el detalle del libro.'
        );
      });

    return () => controller.abort();
  }, [bookId, retryToken]);

  return (
    <Modal open={!!bookId} onClose={onClose} title="Ficha del libro" maxWidth={820}>
      {state === 'loading' && (
        <div style={{ padding: 24, color: 'var(--text-2)' }}>Cargando detalle…</div>
      )}

      {(state === 'error' || state === 'unavailable') && (
        <div className="stack" style={{ padding: 16 }}>
          <div style={{ color: 'var(--danger)', fontSize: 13 }}>{message}</div>
          <button type="button" className="btn" onClick={() => setRetryToken(value => value + 1)}>
            Reintentar
          </button>
        </div>
      )}

      {state === 'loaded' && book && (
        <div
          className="stack"
          style={{ gap: 16 }}
          data-server-book-id={book.serverId}
          data-legacy-book-id={book.legacyId}
        >
          <div style={{ fontSize: 12, color: 'var(--text-3)' }}>Vista de solo lectura · datos del servidor</div>
          <div className="book-detail">
            <div className="detail-section">
              <div className="detail-section-title">Datos bibliográficos</div>
              <div className="stack" style={{ gap: 10 }}>
                <div className="detail-grid">
                  <div><div className="detail-label">Núm. consecutivo</div><div className="detail-value text-mono">{catalogValue(book.catalogNumber)}</div></div>
                  <div><div className="detail-label">Código de barras / inventario</div><div className="detail-value text-mono">{catalogValue(book.inventoryNumber)}</div></div>
                </div>
                <div><div className="detail-label">Serie o colección</div><div className="detail-value">{catalogValue(book.seriesCollection)}</div></div>
                <div><div className="detail-label">Título</div><div className="detail-value fw-600 text-serif" style={{ fontSize: 16 }}>{catalogValue(book.title)}</div></div>
                <div><div className="detail-label">Autor</div><div className="detail-value">{catalogValue(book.author)}</div></div>
                <div><div className="detail-label">Mención de responsabilidad</div><div className="detail-value">{catalogValue(book.responsibilityMention)}</div></div>
                <div><div className="detail-label">Pie de imprenta</div><div className="detail-value">{catalogValue(book.imprint)}</div></div>
                <div><div className="detail-label">Clasificación</div><div className="detail-value text-mono text-sm">{catalogValue(book.classification)}</div></div>
                <div className="detail-grid">
                  <div><div className="detail-label">Año</div><div className="detail-value">{catalogValue(book.publicationYear)}</div></div>
                  <div><div className="detail-label">Idioma</div><div className="detail-value">{catalogValue(book.language)}</div></div>
                  <div><div className="detail-label">Páginas</div><div className="detail-value">{catalogValue(book.totalPages)}</div></div>
                  <div><div className="detail-label">Estado físico</div><div className="detail-value">{catalogValue(book.physicalCondition)}</div></div>
                </div>
                <div><div className="detail-label">Código de barras</div><div className="detail-value text-mono text-sm">{catalogValue(book.barcode)}</div></div>
                <div><div className="detail-label">ISBN</div><div className="detail-value text-mono text-sm">{catalogValue(book.isbn)}</div></div>
              </div>
            </div>

            <div className="stack" style={{ gap: 16 }}>
              <div className="detail-section">
                <div className="detail-section-title">Estado del proceso</div>
                <div className="detail-grid">
                  <div><div className="detail-label">Etapa</div><div className="mt-4"><CatalogBadge value={book.currentStage} catalog={window.bookCatalogs.stages}/></div></div>
                  <div><div className="detail-label">Estado</div><div className="mt-4"><CatalogBadge value={book.status} catalog={window.bookCatalogs.statuses}/></div></div>
                  <div><div className="detail-label">Prioridad</div><div className="mt-4"><CatalogBadge value={book.priority} catalog={window.bookCatalogs.priorities}/></div></div>
                  <div><div className="detail-label">Proyecto</div><div className="detail-value text-sm">{catalogValue(book.project?.name)}</div></div>
                </div>
              </div>

              <div className="detail-section">
                <div className="detail-section-title">Observaciones</div>
                <div className="detail-value text-sm">{catalogValue(book.observations)}</div>
              </div>

              <div className="detail-section">
                <div className="detail-section-title">Registro</div>
                <div className="detail-grid">
                  <div><div className="detail-label">Creado</div><div className="detail-value text-sm">{catalogValue(book.createdAt)}</div></div>
                  <div><div className="detail-label">Actualizado</div><div className="detail-value text-sm">{catalogValue(book.updatedAt)}</div></div>
                </div>
              </div>
            </div>
          </div>
        </div>
      )}
    </Modal>
  );
};

const ServerCatalogo = ({ onSessionExpired }) => {
  const [searchInput, setSearchInput] = useState('');
  const [search, setSearch] = useState('');
  const [currentStage, setCurrentStage] = useState('');
  const [statusFilter, setStatusFilter] = useState('');
  const [priority, setPriority] = useState('');
  const [sort, setSort] = useState('updated_at');
  const [direction, setDirection] = useState('desc');
  const [page, setPage] = useState(1);
  const [catalogState, setCatalogState] = useState('loading');
  const [items, setItems] = useState([]);
  const [pagination, setPagination] = useState({ page: 1, per_page: 20, total: 0, total_pages: 0 });
  const [errorMessage, setErrorMessage] = useState('');
  const [retryToken, setRetryToken] = useState(0);
  const [selectedBookId, setSelectedBookId] = useState(null);
  const requestRef = useRef(0);

  useEffect(() => {
    const timeoutId = window.setTimeout(() => {
      setPage(1);
      setSearch(searchInput.trim());
    }, 300);
    return () => window.clearTimeout(timeoutId);
  }, [searchInput]);

  useEffect(() => {
    const controller = new AbortController();
    const requestId = ++requestRef.current;
    setCatalogState('loading');
    setErrorMessage('');

    window.booksService.listBooks({
      search,
      current_stage: currentStage,
      status: statusFilter,
      priority,
      page,
      per_page: 20,
      sort,
      direction,
      signal: controller.signal
    }).then((result) => {
      if (controller.signal.aborted || requestId !== requestRef.current) return;
      setItems(result.items);
      setPagination(result.pagination);
      setCatalogState(result.items.length === 0 ? 'empty' : 'loaded');
    }).catch((error) => {
      if (controller.signal.aborted || requestId !== requestRef.current) return;
      setItems([]);
      if (error?.status === 401) {
        onSessionExpired();
        return;
      }
      if (error?.status === 403) {
        setCatalogState('error');
        setErrorMessage('No tienes permiso para consultar el catálogo.');
        return;
      }
      setCatalogState(error?.status === 0 || error?.status >= 500 ? 'unavailable' : 'error');
      setErrorMessage(
        error?.status === 0 || error?.status >= 500
          ? 'No fue posible conectar con el servicio de libros.'
          : 'No fue posible obtener el catálogo.'
      );
    });

    return () => controller.abort();
  }, [search, currentStage, statusFilter, priority, page, sort, direction, retryToken]);

  const updateFilter = (setter) => (event) => {
    setter(event.target.value);
    setPage(1);
  };

  const clearFilters = () => {
    setSearchInput('');
    setSearch('');
    setCurrentStage('');
    setStatusFilter('');
    setPriority('');
    setSort('updated_at');
    setDirection('desc');
    setPage(1);
  };

  const canGoBack = page > 1 && catalogState !== 'loading';
  const canGoForward = page < pagination.total_pages && catalogState !== 'loading';

  return (
    <div className="stack">
      <div className="card">
        <div className="card-header">
          <Icon name="library" size={16} style={{ color: 'var(--text-2)' }}/>
          <div>
            <div className="card-title">Catálogo de libros · Base de datos</div>
            <div className="card-subtitle">
              {pagination.total} libros · servidor · solo lectura · click en fila para ver detalle
            </div>
          </div>
          <div className="spacer"/>
        </div>

        <div style={{ padding: '14px 20px', borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '2fr repeat(3, minmax(140px, 1fr))', gap: 10 }}>
            <div style={{ position: 'relative' }}>
              <Icon name="search" size={14} style={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)', color: 'var(--text-3)' }}/>
              <input
                type="text"
                className="input"
                placeholder="Buscar por título, autor, inventario, ISBN o código de barras..."
                value={searchInput}
                onChange={event => setSearchInput(event.target.value)}
                style={{ paddingLeft: 32 }}
              />
            </div>
            <select className="select" aria-label="Filtrar por etapa" value={currentStage} onChange={updateFilter(setCurrentStage)}>
              <option value="">Todas las etapas</option>
              {Object.entries(window.bookCatalogs.stages).map(([value, label]) => <option key={value} value={value}>{label}</option>)}
            </select>
            <select className="select" aria-label="Filtrar por estado" value={statusFilter} onChange={updateFilter(setStatusFilter)}>
              <option value="">Todos los estados</option>
              {Object.entries(window.bookCatalogs.statuses).map(([value, label]) => <option key={value} value={value}>{label}</option>)}
            </select>
            <select className="select" aria-label="Filtrar por prioridad" value={priority} onChange={updateFilter(setPriority)}>
              <option value="">Todas las prioridades</option>
              {Object.entries(window.bookCatalogs.priorities).map(([value, label]) => <option key={value} value={value}>{label}</option>)}
            </select>
            <select className="select" aria-label="Ordenar catálogo" value={sort} onChange={updateFilter(setSort)}>
              <option value="updated_at">Actualización</option>
              <option value="inventory_number">Inventario</option>
              <option value="title">Título</option>
              <option value="author">Autor</option>
              <option value="publication_year">Año</option>
              <option value="current_stage">Etapa</option>
              <option value="status">Estado</option>
              <option value="priority">Prioridad</option>
            </select>
            <select className="select" aria-label="Dirección de orden" value={direction} onChange={updateFilter(setDirection)}>
              <option value="asc">Ascendente</option>
              <option value="desc">Descendente</option>
            </select>
            <button type="button" className="btn" onClick={clearFilters}>Limpiar filtros</button>
          </div>
        </div>

        {(catalogState === 'error' || catalogState === 'unavailable') && (
          <div style={{ padding: 20, borderBottom: '1px solid var(--border)' }}>
            <div style={{ color: 'var(--danger)', fontSize: 13, marginBottom: 10 }}>{errorMessage}</div>
            <button type="button" className="btn" onClick={() => setRetryToken(value => value + 1)}>Reintentar</button>
          </div>
        )}

        <div className="table-wrap" style={{ border: 'none', borderRadius: 0, maxHeight: 600 }}>
          <table className="data">
            <thead>
              <tr>
                <th>Núm.</th>
                <th>Serie / Título</th>
                <th>Autor</th>
                <th>Pie de imprenta</th>
                <th>Clasificación</th>
                <th>Código de barras</th>
                <th style={{ textAlign: 'right' }}>Págs.</th>
                <th>Etapa</th>
                <th>Estado</th>
              </tr>
            </thead>
            <tbody>
              {catalogState === 'loading' && (
                <tr><td colSpan="9" style={{ padding: 28, textAlign: 'center', color: 'var(--text-2)' }}>Cargando catálogo…</td></tr>
              )}
              {catalogState === 'empty' && (
                <tr><td colSpan="9" style={{ padding: 28, textAlign: 'center', color: 'var(--text-2)' }}>No se encontraron libros con los filtros seleccionados.</td></tr>
              )}
              {catalogState === 'loaded' && items.map(book => (
                <tr
                  key={window.entityIdMapper.buildStableBookKey(book)}
                  onClick={() => book.serverId && setSelectedBookId(book.serverId)}
                  style={{ cursor: book.serverId ? 'pointer' : 'default' }}
                >
                  <td><span className="cons">#{catalogValue(book.catalogNumber)}</span></td>
                  <td className="title-cell">
                    <div className="text-xs text-3">{catalogValue(book.seriesCollection)}</div>
                    <div className="title-line">{catalogValue(book.title)}</div>
                  </td>
                  <td className="text-sm text-2">{catalogValue(book.author)}</td>
                  <td className="text-sm text-2">
                    <div>{catalogValue(book.imprint)}</div>
                    <div className="text-xs text-3">{catalogValue(book.publicationYear)}</div>
                  </td>
                  <td className="text-mono text-xs text-2">{catalogValue(book.classification)}</td>
                  <td className="text-mono text-xs text-2">{catalogValue(book.barcode)}</td>
                  <td style={{ textAlign: 'right' }} className="text-mono text-sm">{catalogValue(book.totalPages)}</td>
                  <td><CatalogBadge value={book.currentStage} catalog={window.bookCatalogs.stages}/></td>
                  <td><CatalogBadge value={book.status} catalog={window.bookCatalogs.statuses}/></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>

        <div className="row" style={{ padding: '12px 20px', justifyContent: 'space-between', borderTop: '1px solid var(--border)' }}>
          <div className="text-sm text-2">Página {pagination.page} de {pagination.total_pages || 1}</div>
          <div className="row" style={{ gap: 8 }}>
            <button type="button" className="btn" disabled={!canGoBack} onClick={() => setPage(value => Math.max(1, value - 1))}>Anterior</button>
            <button type="button" className="btn" disabled={!canGoForward} onClick={() => setPage(value => value + 1)}>Siguiente</button>
          </div>
        </div>
      </div>

      <ServerBookDetail
        bookId={selectedBookId}
        onClose={() => setSelectedBookId(null)}
        onSessionExpired={onSessionExpired}
      />
    </div>
  );
};

const LocalCatalogo = ({ libros, onSelectBook }) => {
  const [q, setQ] = useState('');
  const [filterSerie, setFilterSerie] = useState('');
  const [filterEstatus, setFilterEstatus] = useState('');

  const filtrados = useMemo(() => libros.filter(book => {
    if (q && !(book.titulo.toLowerCase().includes(q.toLowerCase())
      || book.autor.toLowerCase().includes(q.toLowerCase())
      || book.cons.includes(q)
      || book.codigoBarras.includes(q))) return false;
    if (filterSerie && book.serie !== filterSerie) return false;
    if (filterEstatus && book.estatus !== filterEstatus) return false;
    return true;
  }), [libros, q, filterSerie, filterEstatus]);

  return (
    <div className="stack">
      <div className="card">
        <div className="card-header">
          <Icon name="library" size={16} style={{ color: 'var(--text-2)' }}/>
          <div>
            <div className="card-title">Catálogo de libros · Base de datos</div>
            <div className="card-subtitle">{filtrados.length} de {libros.length} libros · demo local</div>
          </div>
        </div>
        <div style={{ padding: '14px 20px', borderBottom: '1px solid var(--border)', background: 'var(--surface-2)' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '2fr 1fr 1fr', gap: 10 }}>
            <input className="input" placeholder="Buscar por título, autor, núm. de control o código de barras..." value={q} onChange={event => setQ(event.target.value)}/>
            <select className="select" value={filterSerie} onChange={event => setFilterSerie(event.target.value)}>
              <option value="">Todas las series</option>
              {APP_DATA.SERIES.map(series => <option key={series} value={series}>{series}</option>)}
            </select>
            <select className="select" value={filterEstatus} onChange={event => setFilterEstatus(event.target.value)}>
              <option value="">Todos los estatus</option>
              {Object.entries(APP_DATA.ESTATUS).map(([key, value]) => <option key={key} value={key}>{value.label}</option>)}
            </select>
          </div>
        </div>
        <div className="table-wrap" style={{ border: 'none', borderRadius: 0, maxHeight: 600 }}>
          <table className="data">
            <thead><tr><th>Núm.</th><th>Serie</th><th>Título · Autor</th><th>Clasificación</th><th>Págs.</th><th>Estatus</th></tr></thead>
            <tbody>
              {filtrados.map(book => (
                <tr key={book.cons} onClick={() => onSelectBook(book)} style={{ cursor: 'pointer' }}>
                  <td><span className="cons">#{book.cons}</span></td>
                  <td className="text-sm text-2">{book.serie}</td>
                  <td className="title-cell"><div className="title-line">{book.titulo}</div><div className="author-line">{book.autor}</div></td>
                  <td className="text-mono text-xs text-2">{book.clasificacion}</td>
                  <td className="text-mono text-sm">{book.paginas}</td>
                  <td><StatusPill estatus={book.estatus}/></td>
                </tr>
              ))}
            </tbody>
          </table>
        </div>
      </div>
    </div>
  );
};

const Catalogo = ({ libros, onSelectBook, onSessionExpired }) => {
  const isServerMode = window.APP_CONFIG.AUTH.MODE === 'server';
  if (isServerMode) return <ServerCatalogo onSessionExpired={onSessionExpired}/>;
  return <LocalCatalogo libros={libros} onSelectBook={onSelectBook}/>;
};

// Detalle local heredado para los demás módulos y para local_demo.
const BookDetail = ({ libro, onClose }) => {
  if (!libro) return null;
  const dig = getUser(libro.digitalizadoPor);
  const ed = getUser(libro.editadoPor);
  const cc = getUser(libro.ccPor);

  return (
    <Modal open={!!libro} onClose={onClose} title={`Ficha del libro #${libro.cons}`} maxWidth={780}>
      <div className="book-detail">
        <div className="detail-section">
          <div className="detail-section-title">Datos del libro</div>
          <div className="stack" style={{ gap: 10 }}>
            <div><div className="detail-label">Núm. Consecutivo</div><div className="detail-value text-mono">#{libro.cons}</div></div>
            <div><div className="detail-label">Serie o Colección</div><div className="detail-value">{libro.serie}</div></div>
            <div><div className="detail-label">Título</div><div className="detail-value fw-600 text-serif" style={{ fontSize: 16 }}>{libro.titulo}</div></div>
            <div><div className="detail-label">Autor</div><div className="detail-value">{libro.autor}</div></div>
            <div><div className="detail-label">Mención de responsabilidad</div><div className="detail-value text-sm">{libro.mencion}</div></div>
            <div><div className="detail-label">Pie de imprenta</div><div className="detail-value text-sm">{libro.pieImprenta}</div></div>
            <div className="detail-grid">
              <div><div className="detail-label">Páginas</div><div className="detail-value">{libro.paginas}</div></div>
              <div><div className="detail-label">Código de barras</div><div className="detail-value text-mono text-sm">{libro.codigoBarras}</div></div>
            </div>
            <div><div className="detail-label">Clasificación</div><div className="detail-value text-mono text-sm">{libro.clasificacion}</div></div>
          </div>
        </div>

        <div className="stack" style={{ gap: 16 }}>
          <div className="detail-section">
            <div className="detail-section-title">Proceso de digitalización</div>
            <div className="detail-grid">
              <div><div className="detail-label">Fecha</div><div className="detail-value text-sm">{fmtDate(libro.fechaDigitalizacion)}</div></div>
              <div><div className="detail-label">Digitalizado por</div><div className="detail-value text-sm">{dig?.nombre || '—'}</div></div>
              <div><div className="detail-label">Imágenes</div><div className="detail-value text-mono">{fmtNum(libro.imagenesResultantes)}</div></div>
              <div><div className="detail-label">Acumulado</div><div className="detail-value text-mono">{fmtNum(libro.acumuladoImagenes)}</div></div>
            </div>
          </div>

          <div className="detail-section">
            <div className="detail-section-title">Proceso de edición</div>
            <div className="detail-grid">
              <div><div className="detail-label">Fecha</div><div className="detail-value text-sm">{fmtDate(libro.fechaEdicion)}</div></div>
              <div><div className="detail-label">Editado por</div><div className="detail-value text-sm">{ed?.nombre || '—'}</div></div>
            </div>
            {libro.cortes && (
              <div className="mt-12">
                <div className="detail-label">Cortes horarios</div>
                <div className="text-mono text-sm text-2 mt-4">
                  11:00 → {libro.cortes.c11} · 13:00 → {libro.cortes.c13} · 16:00 → {libro.cortes.c16} · 18:00 → {libro.cortes.c18}
                </div>
              </div>
            )}
          </div>

          <div className="detail-section">
            <div className="detail-section-title">Control de calidad</div>
            <div className="detail-grid">
              <div><div className="detail-label">Fecha</div><div className="detail-value text-sm">{fmtDate(libro.fechaControlCalidad)}</div></div>
              <div><div className="detail-label">Revisado por</div><div className="detail-value text-sm">{cc?.nombre || '—'}</div></div>
            </div>
            <div className="mt-12"><div className="detail-label">Estatus</div><div className="mt-4"><StatusPill estatus={libro.estatus}/></div></div>
            {libro.observaciones && (
              <div className="mt-12">
                <div className="detail-label">Observaciones</div>
                <div className="text-sm mt-4" style={{ padding: 8, background: 'var(--danger-soft)', color: 'var(--danger)', borderRadius: 4 }}>
                  {libro.observaciones}
                </div>
              </div>
            )}
          </div>

          <div className="detail-section">
            <div className="detail-section-title">Conversión</div>
            <div className="detail-grid">
              <div><div className="detail-label">Fecha</div><div className="detail-value text-sm">{fmtDate(libro.fechaConversion)}</div></div>
              <div><div className="detail-label">Status final</div><div className="detail-value text-sm fw-600">{libro.statusFinal || '—'}</div></div>
            </div>
            <div className="mt-12">
              <div className="detail-label mb-4">Formatos</div>
              <div className="row" style={{ flexWrap: 'wrap', gap: 6 }}>
                {[
                  ['JPG', libro.edicionJpg], ['TIFF', libro.conversionTiff],
                  ['PDF Color', libro.pdfColor], ['PDF B&N', libro.pdfBn], ['EPUB', libro.epub]
                ].map(([label, done]) => (
                  <span key={label} className="badge" style={{
                    background: done ? 'var(--success-soft)' : 'var(--surface-2)',
                    color: done ? 'var(--success)' : 'var(--text-3)',
                    padding: '4px 10px', fontSize: 12,
                  }}>
                    {done ? '✓' : '·'} {label}
                  </span>
                ))}
              </div>
            </div>
          </div>
        </div>
      </div>
    </Modal>
  );
};

Object.assign(window, { Catalogo, BookDetail });
