/**
 * The shared visual language for "what did AI decide on this prompt":
 * per-engine verdict chips and the "Won by" rival chips. Used by the
 * wins/losses cards on Overview and by every card on the Tracked Prompts
 * tab, so a verdict reads identically wherever the merchant meets it.
 */

import React from 'react';

import type {
  WinLossEngineOutcome,
  WinLossRival,
} from '../../service/visibility/visibility.interface';

import { sentimentToTone } from './helpers';
import Pill from './Pill';

/** Props for {@link EngineOutcomeChips}. */
interface EngineOutcomeChipsProps {
  /** The week's per-engine verdicts for one prompt. */
  outcomes: WinLossEngineOutcome[];
}

/**
 * The prompt's verdict, as ONE chip. Engines are deliberately not named: a
 * row that spelled out every engine it asked turned into a wall of vendor
 * names, and two chips contradicting each other ("mentioned" beside "not
 * mentioned") read as a bug rather than as coverage. The merchant gets the
 * one answer they act on: were you in the answer, and how high.
 *
 * @param {EngineOutcomeChipsProps} props - The week's verdicts, one entry per
 *   engine that answered.
 * @returns {JSX.Element | null} The chip row, or ``null`` without verdicts.
 */
export const EngineOutcomeChips = ({
  outcomes,
}: EngineOutcomeChipsProps): JSX.Element | null => {
  if (outcomes.length === 0) return null;

  const mentioning = outcomes.filter(outcome => outcome.mentioned);
  const mentioned = mentioning.length > 0;
  // Best rank the brand held anywhere it was named.
  const bestPosition = mentioning.reduce<number | null>(
    (best, outcome) =>
      outcome.position !== null && (best === null || outcome.position < best)
        ? outcome.position
        : best,
    null
  );
  const sentiment =
    mentioning.find(outcome => outcome.sentiment)?.sentiment ?? null;

  return (
    <span className="flex flex-wrap items-center gap-1.5">
      <Pill size="sm" tone={mentioned ? 'success' : 'critical'}>
        AI
        {' · '}
        {mentioned ? (
          bestPosition !== null ? (
            <span className="font-bold">{`#${bestPosition}`}</span>
          ) : (
            'mentioned'
          )
        ) : (
          'not mentioned'
        )}
      </Pill>
      {sentiment && (
        <Pill size="sm" tone={sentimentToTone(sentiment)}>
          {sentiment}
        </Pill>
      )}
    </span>
  );
};

/** Props for {@link WonByChips}. */
interface WonByChipsProps {
  /** Ranked rivals the AI named on this prompt. */
  rivals: WinLossRival[];
  /**
   * Lead-in word before the chips. "Won by" only fits a prompt the brand
   * LOST; where the brand is in the answer the rivals merely share it. An
   * empty string renders no lead-in at all, for callers that print the label
   * on its own line above the chips.
   */
  label?: string;
}

/**
 * Rival chips: the competitors the AI named on this prompt, with their
 * leaderboard share of voice when they made it.
 *
 * @param {WonByChipsProps} props - Ranked rivals plus the lead-in word.
 * @returns {JSX.Element} The chip row.
 */
export const WonByChips = ({
  rivals,
  label = 'Won by',
}: WonByChipsProps): JSX.Element => (
  <span className="flex flex-wrap items-center gap-1.5 text-xs text-gray-500">
    {/* An empty label means the caller put it on its own line above. */}
    {label || null}
    {rivals.map(rival => (
      <Pill
        key={rival.domain || rival.name || 'rival'}
        size="sm"
        tone="warning"
      >
        <span className="font-semibold">{rival.name || rival.domain}</span>
        {rival.share_of_voice !== null ? ` · ${rival.share_of_voice}% SOV` : ''}
      </Pill>
    ))}
  </span>
);
