// Local file upload card — sits alongside the Slack and Databricks cards on the
// Connectors page (see connectors.jsx). Same shape as those: logo, live status
// line, one action.
//
// Unlike the connector cards there is nothing to authorize, so the status is a
// count of what has actually been ingested (GET /ingestion/files, which excludes
// connector-loaded content) plus live progress broadcast by the upload drawer
// while a batch is running. Reading the count from the backend rather than from
// drawer state means the card is still right after a page reload.

const { useState: useOup, useEffect: useOupEffect, useRef: useOupRef } = React;

const OUP_POLL_MS = 15000;

function oupLive() {
  try { return !!(typeof parcleApiBase === 'function' && parcleApiBase()); }
  catch (e) { return false; }
}

// One ordered decision for text + dot, so they can never disagree.
// Returns [line, dotKind].
function oupStatus({ loading, unreachable, progress, total, queryable }) {
  const batch = progress && progress.total ? progress : null;
  if (batch && batch.active) {
    // Count everything that has FINISHED, not just the successes — otherwise a
    // batch where files fail sits at "Uploading 0 of 3…" and reads as stuck.
    const finished = (batch.done || 0) + (batch.failed || 0);
    return [`Uploading ${finished} of ${batch.total}…`, 'syncing'];
  }
  if (batch && batch.done === 0 && batch.failed === batch.total) {
    // Nothing got through — say so rather than falling back to the stored count,
    // which would look like the upload silently succeeded.
    return [`Couldn't upload ${batch.total} file${batch.total === 1 ? '' : 's'}`, 'error'];
  }
  if (loading) return ['Checking uploads…', 'paused'];
  // Only admit we're offline when there is nothing known to show; a blip must
  // not replace "42 files in memory" with an error (same rule as the other cards).
  if (unreachable && !total) return ["Can't reach Parcle — retrying…", 'paused'];
  if (!total) return ['No files uploaded yet', 'paused'];
  const files = `${total} file${total === 1 ? '' : 's'} in memory`;
  if (queryable) {
    return [`${files} · ${queryable} queryable with SQL`, 'live'];
  }
  return [files, 'live'];
}

function OrgUploadCard({ onUpload }) {
  const [total, setTotal] = useOup(0);
  const [queryable, setQueryable] = useOup(0);
  const [loading, setLoading] = useOup(true);
  const [unreachable, setUnreachable] = useOup(false);
  const [progress, setProgress] = useOup(null);
  const alive = useOupRef(true);

  useOupEffect(() => () => { alive.current = false; }, []);

  const refresh = async () => {
    try {
      // limit=0: the card only needs the two counts, so don't ship a file list
      // on every poll.
      const r = await ParcleUploadAPI.files(0);
      if (!alive.current) return;
      setTotal(r.total || 0);
      setQueryable(r.queryable || 0);
      setUnreachable(false);
    } catch (e) {
      // Keep the last known counts — a blip must not make it read "No files
      // uploaded yet" when the org has plenty.
      if (alive.current) setUnreachable(true);
    } finally {
      if (alive.current) setLoading(false);
    }
  };

  useOupEffect(() => { refresh(); }, []);

  // Slow poll so a colleague's upload (or an ingestion that finished after the
  // drawer closed) eventually shows up.
  useOupEffect(() => {
    const t = setInterval(refresh, OUP_POLL_MS);
    return () => clearInterval(t);
  }, []);

  // Live progress from the drawer, plus a refresh the moment a batch finishes so
  // the count catches up without waiting for the next poll. Trigger on the
  // active→idle EDGE: reacting to "not busy" alone would also fire on the frame
  // where files are merely queued (nothing uploading yet).
  const wasActive = useOupRef(false);
  useOupEffect(() => {
    const onChanged = (e) => {
      const detail = (e && e.detail) || null;
      // A refresh-only announce (e.g. after a delete in the drawer) carries no
      // queue state — re-read the counts without clobbering batch progress.
      if (detail && detail.refresh) { refresh(); return; }
      setProgress(detail);
      const active = !!(detail && detail.active);
      if (wasActive.current && !active) refresh();
      wasActive.current = active;
    };
    window.addEventListener(PARCLE_UPLOAD_EVENT, onChanged);
    return () => window.removeEventListener(PARCLE_UPLOAD_EVENT, onChanged);
  }, []);

  const [statusLine, dotKind] = oupStatus({ loading, unreachable, progress, total, queryable });
  // Failures stay visible until the user clears the batch in the drawer — this
  // card is the only place they'd notice a file didn't make it, so it must not
  // quietly disappear. Suppressed when the line already says nothing got through.
  const allFailed = progress && progress.total && progress.failed === progress.total;
  const failed = (progress && !allFailed) ? progress.failed : 0;

  return (
    // The whole card opens the drawer — that's where the ingested-file list
    // (and per-file deletion) lives, not just the upload flow.
    <div className="card" onClick={onUpload}
      style={{ padding: '18px 22px', marginTop: 24, cursor: 'pointer' }}>
      <div style={{ display: 'flex', alignItems: 'center', gap: 14 }}>
        <VendorLogo vendor="upload" size={36} radius={9}/>
        <div style={{ flex: 1 }}>
          <div style={{ display: 'flex', alignItems: 'baseline', gap: 8 }}>
            <span className="t-h3">Local Files Upload</span>
            <span className="chip accent" style={{ fontSize: 10, height: 20 }}>Live</span>
          </div>
          <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 3 }}>
            <StatusDot size={6} kind={dotKind}/>
            <span className="mono-sm mono text-secondary">{statusLine}</span>
            {!!failed && (
              <span className="mono-sm mono" style={{ color: 'var(--error)' }}>
                · {failed} failed
              </span>
            )}
          </div>
        </div>
        <button className="btn accent" onClick={(e) => { e.stopPropagation(); onUpload(); }}>
          <Icons.Upload size={13}/> Upload files
        </button>
      </div>

      {!total && !(progress && progress.busy) && (
        <div className="text-secondary t-small" style={{ marginTop: 10 }}>
          Add documents and spreadsheets from this computer — PDF, Word, PowerPoint,
          Markdown, CSV, Excel and SQLite/DuckDB files, up to
          {' '}{Math.round(PARCLE_UPLOAD_MAX_BYTES / (1024 * 1024))}MB each. Documents
          become searchable; datasets become tables the agent can query with SQL.
        </div>
      )}
    </div>
  );
}

function OrgUploadSection({ onUpload }) {
  if (!oupLive()) return null;
  return <OrgUploadCard onUpload={onUpload}/>;
}

Object.assign(window, { OrgUploadSection, oupStatus });
