/**
 * Storage Monitor — library pane footer (spec §02 → Storage Monitor;
 * docs/architecture/10 → "Resolved — storage composition indicator").
 *
 * Shows what local storage is *made of* — Snippets, Datasets, and App (the
 * precached shell + overhead) — as a proportional bar plus a labelled legend.
 * It is **not** a "used of quota" gauge: the browser's `quota` is an unreliable
 * padded approximation, so we show real measured sizes instead and let the genuine
 * out-of-room moment surface where it happens (a save-failure toast).
 *
 * Accessibility (council → APG meter / NN/g / WCAG 1.4.1): the bar is **decorative**
 * (`aria-hidden`) and carries no role="meter" — a meter needs a meaningful maximum,
 * which we don't have. The **legend is the source of truth**: real text labels +
 * sizes that assistive tech reads, so meaning never rests on colour alone.
 *
 * Snippet/dataset bytes are measured from our own stores (always available); the
 * App segment needs the origin estimate, so it appears only when that resolves.
 */

import { useEffect, useMemo, useState } from 'react';
import {
  humanizeBytes,
  jsonByteSize,
  STORAGE_MONITOR_MIN_USER_BYTES,
  summarizeStorage,
} from '@core/storage-estimate';
import { readOriginUsage } from '../infrastructure/storage-estimate';
import { useSnippetStore } from '../stores/SnippetStore';
import { useDatasetStore } from '../stores/DatasetStore';
import styles from './StorageMonitor.module.css';

/** Segment key → its colour class (shared by the bar slice and the legend swatch). */
const SEGMENT_CLASS = {
  snippets: styles.segSnippets,
  datasets: styles.segDatasets,
  app: styles.segApp,
} as const;

export default function StorageMonitor() {
  const snippets = useSnippetStore((s) => s.snippets);
  const datasets = useDatasetStore((s) => s.datasets);

  // Measure our own data synchronously. Snippets are serialized; datasets already
  // carry a byte `size`. Memoized so we only re-measure when the lists change.
  const snippetBytes = useMemo(
    () => snippets.reduce((n, snip) => n + jsonByteSize(snip), 0),
    [snippets],
  );
  const datasetBytes = useMemo(() => datasets.reduce((n, d) => n + (d.size ?? 0), 0), [datasets]);

  // Stay hidden until the user's own data is worth a glance — below the floor it's
  // ambient noise, and the app shell would dominate the bar anyway (spec §02).
  const belowFloor = snippetBytes + datasetBytes < STORAGE_MONITOR_MIN_USER_BYTES;

  // The origin total is async + optional. Re-read after our data changes, since a
  // save moves usage; undefined when the Storage Manager API is unavailable.
  const [usageBytes, setUsageBytes] = useState<number | undefined>(undefined);
  useEffect(() => {
    let cancelled = false;
    void readOriginUsage().then((u) => {
      if (!cancelled) setUsageBytes(u);
    });
    return () => {
      cancelled = true;
    };
  }, [snippetBytes, datasetBytes]);

  const composition = useMemo(
    () => summarizeStorage({ usageBytes, snippetBytes, datasetBytes }),
    [usageBytes, snippetBytes, datasetBytes],
  );

  // Hidden below the user-data floor, or with nothing measured yet (truly empty).
  if (belowFloor || composition.totalBytes <= 0) return null;

  const { segments, totalBytes } = composition;

  return (
    <div className={styles.monitor} aria-label="Storage in use">
      {/* Decorative composition bar — the legend below is the accessible source. */}
      <div className={styles.track} aria-hidden="true">
        {segments.map((s) =>
          s.bytes > 0 ? (
            <div
              key={s.key}
              className={`${styles.segment} ${SEGMENT_CLASS[s.key]}`}
              style={{ width: `${(s.bytes / totalBytes) * 100}%` }}
            />
          ) : null,
        )}
      </div>

      {/* Legend: real text labels + sizes — meaning never rests on colour (WCAG 1.4.1). */}
      <ul className={styles.legend}>
        {segments.map((s) => (
          <li key={s.key} className={styles.legendItem}>
            <span className={`${styles.swatch} ${SEGMENT_CLASS[s.key]}`} aria-hidden="true" />
            <span className={styles.legendLabel}>{s.label}</span>
            <span className={styles.legendBytes}>{humanizeBytes(s.bytes)}</span>
          </li>
        ))}
      </ul>

      <div className={styles.total}>{humanizeBytes(totalBytes)} in use</div>
    </div>
  );
}
