import React, { useState } from 'react';

import EmptyState from '../agent-analytics/EmptyState';
import type { CompetitorSnapshot } from '../../service/visibility/visibility.interface';

import { faviconUrlFor, formatDelta, toneToBadgeClass } from './helpers';
import ConfirmExcludeCompetitorModal from './ConfirmExcludeCompetitorModal';

/** Rows shown before "Load more"; the long tail is revealed on demand.
 * Manually tracked rivals are always kept regardless of rank. */
const INITIAL_LEADERBOARD_ROWS = 6;
/** How many extra rows each "Load more" click reveals. */
const LEADERBOARD_ROWS_STEP = 6;

/** Props for {@link CompetitorsTable}. */
interface CompetitorsTableProps {
  /** Competitor snapshots for the selected week (ordered by SOV desc). */
  competitors: CompetitorSnapshot[];
  /** Merchant's own brand snapshot, pinned at the top of the
   *  leaderboard. Shown even when share-of-voice is 0% so the merchant
   *  always sees their own row alongside the rivals. */
  ownBrand?: {
    name: string;
    domain: string;
    shareOfVoice: number;
    deltaSov: number | null;
    mentionsCount: number | null;
  } | null;
  /** Recomaze client id, passed to the per-row delete action. */
  clientId: string;
  /** Recomaze JWT, passed to the per-row delete action. */
  token: string;
  /** Brand the leaderboard belongs to. */
  brandId: string;
  /**
   * Fired after a competitor is excluded so the parent can refetch the
   * leaderboard. The backend already filters excluded domains, so a plain
   * refetch removes the row from the table.
   */
  onCompetitorExcluded: () => void;
}

/** Props for {@link SampleQueriesPopover}. */
interface SampleQueriesPopoverProps {
  /** Localized sample queries for one competitor; render verbatim. */
  queries: string[];
}

/**
 * Click-to-open list of the sample queries that surfaced one competitor.
 *
 * @param {SampleQueriesPopoverProps} props - Popover props.
 * @returns {JSX.Element} Trigger + absolute-positioned panel.
 */
const SampleQueriesPopover = ({
  queries,
}: SampleQueriesPopoverProps): JSX.Element => {
  const [active, setActive] = useState(false);
  if (queries.length === 0) {
    return <span className="text-xs text-gray-400">-</span>;
  }

  return (
    <div className="relative">
      <button
        type="button"
        onClick={() => setActive(prev => !prev)}
        className="text-sm font-medium text-blue-600 hover:underline"
      >
        {`${queries.length} ${queries.length === 1 ? 'query' : 'queries'}`}
      </button>
      {active && (
        <>
          <div
            className="fixed inset-0 z-40"
            onClick={() => setActive(false)}
            aria-hidden="true"
          />
          <div className="absolute right-0 z-50 mt-2 w-80 max-w-[calc(100vw-2rem)] bg-white border border-gray-200 rounded-lg shadow-lg max-h-64 overflow-auto">
            <ul className="divide-y divide-gray-100">
              {queries.map((query, idx) => (
                <li key={idx} className="px-3 py-2 text-sm text-gray-800">
                  {query}
                </li>
              ))}
            </ul>
          </div>
        </>
      )}
    </div>
  );
};

/**
 * Competitor leaderboard: Domain | SOV | Δ vs last week | Mentions |
 * Sample queries | Actions. Rows the merchant manually tracks carry a
 * badge. The last column holds a delete button that suppresses the
 * domain from the leaderboard and from future scans.
 *
 * @param {CompetitorsTableProps} props - Table props.
 * @returns {JSX.Element} The leaderboard table.
 */
const CompetitorsTable = ({
  competitors,
  ownBrand,
  clientId,
  token,
  brandId,
  onCompetitorExcluded,
}: CompetitorsTableProps): JSX.Element => {
  const [excludeTarget, setExcludeTarget] = useState<CompetitorSnapshot | null>(
    null
  );
  const [visibleCount, setVisibleCount] = useState(INITIAL_LEADERBOARD_ROWS);

  if (competitors.length === 0 && !ownBrand) {
    return <EmptyState message="No competitors found for this period" />;
  }

  const topRows = competitors.slice(0, visibleCount);
  const seen = new Set(topRows.map(row => row.competitor_domain));
  const visibleCompetitors = [
    ...topRows,
    ...competitors.filter(
      row => row.manually_tracked && !seen.has(row.competitor_domain)
    ),
  ];
  const shownDomains = new Set(
    visibleCompetitors.map(row => row.competitor_domain)
  );
  const remainingCount = competitors.filter(
    row => !shownDomains.has(row.competitor_domain)
  ).length;

  return (
    <>
      <div className="bg-white rounded-xl border border-gray-200 overflow-hidden">
        <div className="overflow-x-auto">
          <table className="min-w-full text-sm">
            <thead className="bg-gray-50 text-left text-xs font-semibold uppercase tracking-wide text-gray-500">
              <tr>
                <th className="px-4 py-3">Domain</th>
                <th className="px-4 py-3 text-right">SOV</th>
                <th className="px-4 py-3">Δ vs last week</th>
                <th className="px-4 py-3 text-right">Mentions</th>
                <th className="px-4 py-3">Sample queries</th>
                <th className="px-4 py-3 w-12" aria-label="Row actions" />
              </tr>
            </thead>
            <tbody className="divide-y divide-gray-100">
              {ownBrand &&
                (() => {
                  const ownDelta = formatDelta(ownBrand.deltaSov, '%');
                  return (
                    <tr key="own-brand-row" className="bg-emerald-50/40">
                      <td className="px-4 py-3">
                        <div className="flex items-center gap-2">
                          <img
                            src={faviconUrlFor(ownBrand.domain)}
                            alt=""
                            width={20}
                            height={20}
                            loading="lazy"
                            style={{
                              borderRadius: 4,
                              background: '#f1f5f9',
                              flexShrink: 0,
                            }}
                            onError={event => {
                              (
                                event.currentTarget as HTMLImageElement
                              ).style.visibility = 'hidden';
                            }}
                          />
                          <span className="text-sm font-semibold text-gray-900">
                            {ownBrand.name}
                          </span>
                          <span
                            className={`inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium ${toneToBadgeClass('success')}`}
                          >
                            Your brand
                          </span>
                        </div>
                      </td>
                      <td className="px-4 py-3 text-right text-sm text-gray-900">
                        {ownBrand.shareOfVoice}%
                      </td>
                      <td className="px-4 py-3">
                        {ownDelta.hidden ? (
                          <span className="text-xs text-gray-400">-</span>
                        ) : (
                          <span
                            className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass(ownDelta.tone)}`}
                          >
                            {ownDelta.label}
                          </span>
                        )}
                      </td>
                      <td className="px-4 py-3 text-right text-sm text-gray-900">
                        {ownBrand.mentionsCount ?? '-'}
                      </td>
                      <td className="px-4 py-3 text-xs text-gray-500">
                        See &ldquo;Tracked prompts&rdquo; below
                      </td>
                      <td className="px-4 py-3" />
                    </tr>
                  );
                })()}
              {visibleCompetitors.map(competitor => {
                const delta = formatDelta(competitor.delta_vs_prev, '%');
                const displayName =
                  competitor.competitor_name || competitor.competitor_domain;

                return (
                  <tr key={competitor.competitor_domain}>
                    <td className="px-4 py-3">
                      <div className="flex items-center gap-2">
                        <img
                          src={faviconUrlFor(competitor.competitor_domain)}
                          alt=""
                          width={20}
                          height={20}
                          loading="lazy"
                          style={{
                            borderRadius: 4,
                            background: '#f1f5f9',
                            flexShrink: 0,
                          }}
                          onError={event => {
                            (
                              event.currentTarget as HTMLImageElement
                            ).style.visibility = 'hidden';
                          }}
                        />
                        <span className="text-sm font-semibold text-gray-900">
                          {displayName}
                        </span>
                        {competitor.manually_tracked && (
                          <span
                            className={`inline-flex items-center rounded-full px-2 py-0.5 text-[10px] font-medium ${toneToBadgeClass('info')}`}
                          >
                            Manually tracked
                          </span>
                        )}
                      </div>
                    </td>
                    <td className="px-4 py-3 text-right text-sm text-gray-900">
                      {competitor.share_of_voice}%
                    </td>
                    <td className="px-4 py-3">
                      {delta.hidden ? (
                        <span className="text-xs text-gray-400">-</span>
                      ) : (
                        <span
                          className={`inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-medium ${toneToBadgeClass(delta.tone)}`}
                        >
                          {delta.label}
                        </span>
                      )}
                    </td>
                    <td className="px-4 py-3 text-right text-sm text-gray-900">
                      {competitor.mentions_count}
                    </td>
                    <td className="px-4 py-3">
                      <SampleQueriesPopover
                        queries={competitor.sample_queries}
                      />
                    </td>
                    <td className="px-4 py-3 text-right">
                      <button
                        type="button"
                        onClick={() => setExcludeTarget(competitor)}
                        aria-label={`Remove ${displayName} from leaderboard`}
                        className="rounded-md p-1.5 text-gray-400 hover:bg-gray-100 hover:text-red-600"
                      >
                        <svg
                          xmlns="http://www.w3.org/2000/svg"
                          width="16"
                          height="16"
                          viewBox="0 0 24 24"
                          fill="none"
                          stroke="currentColor"
                          strokeWidth="2"
                          strokeLinecap="round"
                          strokeLinejoin="round"
                          aria-hidden="true"
                        >
                          <polyline points="3 6 5 6 21 6" />
                          <path d="M19 6l-1.5 14a2 2 0 0 1-2 1.8H8.5a2 2 0 0 1-2-1.8L5 6" />
                          <path d="M10 11v6" />
                          <path d="M14 11v6" />
                          <path d="M9 6V4a2 2 0 0 1 2-2h2a2 2 0 0 1 2 2v2" />
                        </svg>
                      </button>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
        {remainingCount > 0 && (
          <div className="flex justify-center border-t border-gray-200 p-3">
            <button
              type="button"
              onClick={() =>
                setVisibleCount(count => count + LEADERBOARD_ROWS_STEP)
              }
              className="text-sm font-medium text-blue-600 hover:text-blue-700"
            >
              {`Load more (${remainingCount})`}
            </button>
          </div>
        )}
      </div>

      <ConfirmExcludeCompetitorModal
        open={excludeTarget !== null}
        competitor={excludeTarget}
        onClose={() => setExcludeTarget(null)}
        onExcluded={onCompetitorExcluded}
        clientId={clientId}
        token={token}
        brandId={brandId}
      />
    </>
  );
};

export default CompetitorsTable;
