import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Progress } from '@/components/ui/progress';
import { Separator } from '@/components/ui/separator';
import { Skeleton } from '@/components/ui/skeleton';
import { useCurrency } from '@/hooks/use-currency';
import { handleApiError } from '@/lib/error-handler';
import { request } from '@/lib/fetcher';
import { cn } from '@/lib/utils';
import { SharedData } from '@/types';
import { TMarket } from '@/types/market.types';
import { router, usePage } from '@inertiajs/react';
import { BookmarkIcon, BookmarkSimpleIcon } from '@phosphor-icons/react';
import { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';
import { useSWRConfig } from 'swr';

function MarketThumb({
  src,
  label,
  size = 38,
}: {
  src?: string | null;
  label: string;
  size?: number;
}) {
  if (src) {
    return (
      <img
        src={src}
        alt={label}
        className="shrink-0 rounded-[10px] border border-pm-line object-cover"
        style={{ width: size, height: size }}
      />
    );
  }
  return (
    <div
      className="grid shrink-0 place-items-center overflow-hidden rounded-[10px] border border-pm-line text-[9px] font-semibold text-pm-eyebrow"
      style={{
        width: size,
        height: size,
        backgroundImage:
          'repeating-linear-gradient(135deg, var(--pm-surface-2) 0px, var(--pm-surface-2) 5px, var(--pm-bg-sunken) 5px, var(--pm-bg-sunken) 10px)',
      }}
    >
      {label}
    </div>
  );
}

function ProbRing({ pct, size = 42 }: { pct: number; size?: number }) {
  const stroke = 4.5;
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const offset = c * (1 - pct / 100);
  return (
    <div className="relative shrink-0" style={{ width: size, height: size }}>
      <svg width={size} height={size} viewBox={`0 0 ${size} ${size}`}>
        <circle
          cx={size / 2}
          cy={size / 2}
          r={r}
          fill="none"
          stroke="var(--pm-line)"
          strokeWidth={stroke}
        />
        <circle
          cx={size / 2}
          cy={size / 2}
          r={r}
          fill="none"
          stroke="var(--pm-yes)"
          strokeWidth={stroke}
          strokeDasharray={c}
          strokeDashoffset={offset}
          strokeLinecap="round"
          transform={`rotate(-90 ${size / 2} ${size / 2})`}
          style={{ transition: 'stroke-dashoffset .5s ease' }}
        />
      </svg>
      <div className="absolute inset-0 grid place-items-center text-[10px] font-bold text-pm-yes">
        {pct}%
      </div>
    </div>
  );
}

interface MarketGridCardProps {
  market: TMarket;
}

export default function MarketGridCard({ market }: MarketGridCardProps) {
  const { t } = useTranslation();
  const { format } = useCurrency();
  const { auth } = usePage<SharedData>().props;
  const { mutate } = useSWRConfig();
  const [isWatched, setIsWatched] = useState(!!market.is_watched);
  const [watchLoading, setWatchLoading] = useState(false);
  const href = `/markets/${market.slug}`;
  const isBinary = market.type === 'binary';
  const outcomes = market.outcomes ?? [];

  // Deep-link into the market with an outcome preselected for buying so the
  // trade widget is ready the moment the page opens.
  const goTrade = (outcomeId?: number) =>
    router.visit(outcomeId ? `${href}?outcome=${outcomeId}&side=buy` : href);

  const handleWatchlistToggle = async () => {
    if (!auth?.user) {
      router.visit('/login');
      return;
    }
    if (watchLoading) return;

    setWatchLoading(true);
    try {
      const res = await request.post<{ is_watched: boolean }>(
        `/api/user/markets/${market.slug}/watchlist`,
      );
      setIsWatched(res.data.is_watched);
      toast.success(
        res.data.is_watched
          ? t('Added to watchlist.')
          : t('Removed from watchlist.'),
      );
      // Refresh any mounted market lists (e.g. the Watchlist view) so the
      // change is reflected without a manual reload.
      mutate(
        (key) => typeof key === 'string' && key.includes('/api/markets'),
        undefined,
        { revalidate: true },
      );
    } catch (err) {
      handleApiError(err);
    } finally {
      setWatchLoading(false);
    }
  };

  const yesOutcome = outcomes[0];
  const noOutcome = outcomes[1];
  const yesPct = Math.round((yesOutcome?.probability ?? 0.5) * 100);

  const thumbLabel = market.category?.name
    ? market.category.name.slice(0, 4).toUpperCase()
    : market.title.slice(0, 2).toUpperCase();

  const displayOutcomes = isBinary ? [] : outcomes.slice(0, 3);
  const moreCount = isBinary ? 0 : Math.max(0, outcomes.length - 3);

  return (
    <Card
      className="flex cursor-pointer flex-col gap-0 overflow-hidden rounded-2xl border border-[#daeaf9] p-0 py-0 shadow-sm transition-[border-color,box-shadow] hover:border-black/20 hover:shadow-md dark:border-transparent dark:hover:border-white/20"
      onClick={() => router.visit(href)}
    >
      <div className="p-4">
        <div className="mb-3 flex items-start gap-2.5">
          <MarketThumb src={market.image} label={thumbLabel} />
          <div className="min-w-0 flex-1">
            <div className="mb-0.5 text-[9.5px] font-semibold tracking-[0.09em] text-black/40 uppercase dark:text-white/40">
              {market.category?.name ?? t('Market')}
            </div>
            <div className="line-clamp-2 text-sm leading-snug font-semibold text-card-foreground">
              {market.title}
            </div>
          </div>
          {isBinary && <ProbRing pct={yesPct} />}
        </div>

        {isBinary ? (
          <div>
            <div className="mb-2 flex items-baseline gap-2">
              <span className="text-[28px] leading-none font-bold text-card-foreground">
                {yesPct}
                <span className="text-base">%</span>
              </span>
              <span className="text-xs text-black/40 dark:text-white/40">
                {t('chance')} · {yesOutcome?.title ?? t('Yes')}
              </span>
            </div>

            <Progress
              value={yesPct}
              variant="success"
              size="md"
              className="mb-3"
            />

            <div
              className="flex flex-wrap gap-1.5"
              onClick={(e) => e.stopPropagation()}
            >
              <Button
                variant="ghost"
                size="sm"
                onClick={() => goTrade(yesOutcome?.id)}
                className="h-auto min-h-8 flex-1 rounded-md bg-pm-yes-soft font-semibold text-pm-yes-ink hover:bg-pm-yes hover:text-white hover:opacity-100"
              >
                {yesOutcome?.title ?? t('Yes')}
                <span className="text-xs whitespace-break-spaces opacity-85">
                  {format(yesPct / 100)}
                </span>
              </Button>
              <Button
                variant="ghost"
                size="sm"
                onClick={() => goTrade(noOutcome?.id)}
                className="h-auto min-h-8 flex-1 rounded-md bg-pm-no-soft font-semibold text-pm-no-ink hover:bg-pm-no hover:text-white hover:opacity-100"
              >
                {noOutcome?.title ?? t('No')}
                <span className="text-xs whitespace-break-spaces opacity-85">
                  {format((100 - yesPct) / 100)}
                </span>
              </Button>
            </div>
          </div>
        ) : (
          <div
            className="flex flex-col gap-1.5"
            onClick={(e) => e.stopPropagation()}
          >
            {displayOutcomes.map((outcome) => {
              const pct = Math.round((outcome.probability ?? 0) * 100);
              return (
                <Button
                  key={outcome.id}
                  variant="ghost"
                  size="sm"
                  onClick={() => goTrade(outcome.id)}
                  style={{ backgroundColor: outcome.color + '20' }}
                  className="h-auto min-h-8 w-full justify-between rounded-md bg-secondary px-3 py-1.5 hover:bg-pm-yes-soft hover:text-pm-yes-ink hover:opacity-100"
                >
                  <span className="truncate text-sm font-medium">
                    {outcome.title}
                  </span>
                  <span className="ml-2 shrink-0 text-sm font-bold">
                    {pct}%
                  </span>
                </Button>
              );
            })}
            {moreCount > 0 && (
              <Button
                variant="outline"
                size="sm"
                onClick={(e) => {
                  e.stopPropagation();
                  router.visit(href);
                }}
                className="w-full border-dashed border-black/20 dark:border-white/20 dark:text-white/50"
              >
                +{moreCount} {t('more outcomes')}
              </Button>
            )}
          </div>
        )}
      </div>

      <Separator className="mt-auto bg-black/6 dark:bg-white/6" />

      <div className="flex items-center justify-between bg-[#f0f6fb] px-4 py-3 dark:bg-secondary">
        <span className={cn('text-[11.5px] text-black/40 dark:text-white/40')}>
          {format(market.total_volume)} {t('Vol')}
        </span>
        <div className="flex items-center gap-1">
          <Button
            variant="icon"
            size="icon"
            disabled={watchLoading}
            aria-label={
              isWatched ? t('Remove from watchlist') : t('Add to watchlist')
            }
            className="size-8 text-black/30 hover:bg-background dark:text-white/30"
            onClick={(e) => {
              e.stopPropagation();
              handleWatchlistToggle();
            }}
          >
            {isWatched ? (
              <BookmarkSimpleIcon
                weight="fill"
                className="size-5 text-primary"
              />
            ) : (
              <BookmarkIcon weight="regular" className="size-5" />
            )}
          </Button>
        </div>
      </div>
    </Card>
  );
}

export function MarketGridCardSkeleton() {
  return (
    <Card className="gap-0 rounded-[14px] border border-black/6 p-0 py-0 dark:border-white/6">
      <div className="space-y-3 p-4">
        <div className="flex items-start gap-2.5">
          <Skeleton className="size-[38px] shrink-0 rounded-[10px]" />
          <div className="flex-1 space-y-1.5">
            <Skeleton className="h-2.5 w-16" />
            <Skeleton className="h-4 w-full" />
            <Skeleton className="h-4 w-3/4" />
          </div>
        </div>
        <Skeleton className="h-7 w-20" />
        <Skeleton className="h-2 w-full rounded-full" />
        <div className="flex gap-1.5">
          <Skeleton className="h-9 flex-1 rounded-[9px]" />
          <Skeleton className="h-9 flex-1 rounded-[9px]" />
        </div>
      </div>
      <Separator className="bg-black/6 dark:bg-white/6" />
      <div className="flex items-center justify-between px-4 py-3">
        <Skeleton className="h-3 w-16" />
        <div className="flex gap-1">
          <Skeleton className="size-7 rounded-md" />
          <Skeleton className="size-7 rounded-md" />
        </div>
      </div>
    </Card>
  );
}
