'use client';

import Link from 'next/link';
import { ArrowRight } from 'lucide-react';

import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { Skeleton } from '@/components/ui/skeleton';
import type { UmamiMetricRow } from '@/lib/services/umami.service';

interface Props {
  title: string;
  rows: UmamiMetricRow[] | null;
  loading: boolean;
  /** Label substituted when `x` is empty (e.g. direct traffic referrers). */
  defaultLabel?: string;
  /** Optional "View all" link target. When set, renders a link in the
   *  card header that opens a full ranked-list page for this metric. */
  viewAllHref?: string;
  /** Cap for the inline list (default 10). The full page uses no cap. */
  limit?: number;
  /** Optional callback invoked when the empty-state "expand range" CTA is
   *  clicked. When supplied, the empty state shows a nudge button suggesting
   *  the rep try a wider range. */
  onExpandRange?: () => void;
  /** Label for the expand-range button when `onExpandRange` is supplied. */
  expandRangeLabel?: string;
}

/**
 * Compact "top N" list used for top pages / referrers / countries.
 * Renders each row as label + numeric count, with a thin progress bar
 * scaled to the largest count in the set so the visual density tells
 * the same story at a glance as the numbers.
 */
export function TopList({
  title,
  rows,
  loading,
  defaultLabel = '-',
  viewAllHref,
  limit = 10,
  onExpandRange,
  expandRangeLabel = 'Try last 30 days',
}: Props) {
  return (
    <Card>
      <CardHeader className="flex flex-row items-center justify-between gap-2 space-y-0">
        <CardTitle className="text-base">{title}</CardTitle>
        {viewAllHref ? (
          <Link
            // typedRoutes is enabled - viewAllHref is constructed at the
            // call site from string interpolation, so opt out of the
            // literal-string check here.
            // eslint-disable-next-line @typescript-eslint/no-explicit-any
            href={viewAllHref as any}
            className="inline-flex items-center gap-0.5 text-xs font-medium text-muted-foreground hover:text-foreground"
          >
            View all
            <ArrowRight className="size-3" aria-hidden />
          </Link>
        ) : null}
      </CardHeader>
      <CardContent>
        {loading ? (
          <div className="space-y-2">
            <Skeleton className="h-4 w-full" />
            <Skeleton className="h-4 w-5/6" />
            <Skeleton className="h-4 w-4/6" />
            <Skeleton className="h-4 w-3/6" />
          </div>
        ) : !rows || rows.length === 0 ? (
          <div className="space-y-2 py-6 text-center text-sm text-muted-foreground">
            <p>No data in this range.</p>
            {onExpandRange ? (
              <Button size="sm" variant="outline" onClick={onExpandRange}>
                {expandRangeLabel}
              </Button>
            ) : null}
          </div>
        ) : (
          <ul className="space-y-1.5">
            {rows.slice(0, limit).map((row, i) => {
              const max = rows[0]?.y ?? 1;
              const pct = (row.y / max) * 100;
              const label = row.x?.trim() || defaultLabel;
              return (
                <li key={`${row.x}-${i}`} className="text-sm">
                  <div className="flex items-baseline justify-between gap-2">
                    <span className="truncate font-medium">{label}</span>
                    <span className="shrink-0 tabular-nums text-muted-foreground">
                      {row.y.toLocaleString()}
                    </span>
                  </div>
                  <div className="mt-0.5 h-1 w-full rounded-full bg-muted">
                    <div
                      className="h-1 rounded-full bg-brand"
                      style={{ width: `${Math.max(2, pct)}%` }}
                      aria-hidden
                    />
                  </div>
                </li>
              );
            })}
          </ul>
        )}
      </CardContent>
    </Card>
  );
}
