import { useState } from 'react';
import { useQuery } from '../lib/hooks';
import { num, when } from '../lib/format';
import {
  Banner,
  Card,
  EmptyRow,
  Field,
  Loading,
  PageHead,
  TableWrap,
  Tag,
  Tiles,
} from '../components/ui';

interface SearchTerm {
  query: string;
  searches: number;
  viewers: number;
  lastAt: string;
}

interface SearchEvent {
  occurredAt: string;
  userId: string;
  username: string;
  query: string;
}

interface SearchesResponse {
  days: number;
  retentionDays: number;
  totals: { searches: number; queries: number; viewers: number };
  terms: SearchTerm[] | null;
  recent: SearchEvent[] | null;
}

/* Two tables of the same rows on purpose: the summary groups by query and answers "what
   does this house look for", which is what a library is organised against; the log is
   uncollapsed and newest-first and answers "what happened just now", which is the one to
   read when somebody reports that search is not finding something. */

export function SearchesPage() {
  const [days, setDays] = useState(7);
  const { data, error, loading } = useQuery<SearchesResponse>(`/admin/api/searches?days=${days}`);
  const terms = data?.terms ?? [];
  const recent = data?.recent ?? [];
  const totals = data?.totals;

  return (
    <>
      <PageHead
        title="Searches"
        intro="What viewers have been looking for, and what was searched just now."
      />
      <Banner message={error} />

      <Tiles
        tiles={[
          { label: 'searches', value: num(totals?.searches ?? 0), icon: 'search', tone: 'info' },
          { label: 'distinct queries', value: num(totals?.queries ?? 0), icon: 'list', tone: 'data' },
          { label: 'viewers searching', value: num(totals?.viewers ?? 0), icon: 'people', tone: 'note' },
          // Stated rather than assumed: every figure on this page is bounded by how long
          // the table keeps a row, and an operator reading a quiet week has no other way to
          // tell a household that stopped searching from one whose history has aged out.
          {
            label: 'history kept',
            value: `${data?.retentionDays ?? 30} days`,
            small: true,
            icon: 'clock',
          },
        ]}
      />

      {loading ? (
        <Loading />
      ) : (
        <>
          <Card
            title="What the house looks for"
            intro="Queries the search tab ran, grouped without regard to case and labelled with the most recent spelling. Instant search asks from the second character, so a title typed slowly leaves its prefixes here too."
            icon="search"
            tone="info"
            actions={
              <Field label="Window">
                <select value={days} onChange={(event) => setDays(Number(event.target.value))}>
                  <option value={1}>24 hours</option>
                  <option value={7}>7 days</option>
                  <option value={30}>30 days</option>
                </select>
              </Field>
            }
          >
            <TableWrap>
              <table>
                <thead>
                  <tr>
                    <th>Query</th>
                    <th className="num">Searches</th>
                    <th className="num">Viewers</th>
                    <th>Last searched</th>
                  </tr>
                </thead>
                <tbody>
                  {terms.length === 0 ? (
                    <EmptyRow columns={4}>Nothing searched in this window.</EmptyRow>
                  ) : (
                    terms.map((term) => (
                      <tr key={term.query}>
                        <td>{term.query}</td>
                        <td className="num">{num(term.searches)}</td>
                        <td className="num">{num(term.viewers)}</td>
                        <td className="muted nowrap">{when(term.lastAt)}</td>
                      </tr>
                    ))
                  )}
                </tbody>
              </table>
            </TableWrap>
          </Card>

          <Card
            title="As it happened"
            intro="The log, newest first — the query exactly as it was typed, and who typed it. This is the one to read when somebody says search is not finding something."
            icon="history"
            tone="note"
          >
            <TableWrap>
              <table>
                <thead>
                  <tr>
                    <th>When</th>
                    <th>Viewer</th>
                    <th>Query</th>
                  </tr>
                </thead>
                <tbody>
                  {recent.length === 0 ? (
                    <EmptyRow columns={3}>No searches in this window.</EmptyRow>
                  ) : (
                    recent.map((event, index) => (
                      <tr key={`${event.occurredAt}:${index}`}>
                        <td className="muted nowrap">{when(event.occurredAt)}</td>
                        {/* An unattributed search keeps its row and shows the id: the query
                            is the point, and a viewer whose sessions have all expired is
                            still one searcher rather than nobody. */}
                        <td>
                          {event.username || <Tag tone="warn">{event.userId || 'unknown'}</Tag>}
                        </td>
                        <td>{event.query}</td>
                      </tr>
                    ))
                  )}
                </tbody>
              </table>
            </TableWrap>
          </Card>
        </>
      )}
    </>
  );
}
