import DataTable from '@/components/common/data-table';
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from '@/components/ui/accordion';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { Separator } from '@/components/ui/separator';
import { Skeleton } from '@/components/ui/skeleton';
import ClobBook from '@/components/user/default/clob-book';
import ClobTradePanel from '@/components/user/default/clob-trade-panel';
import EmbedDialog from '@/components/user/default/embed-dialog';
import MarketComments from '@/components/user/default/market-comments';
import MarketProbabilityChart, {
  ProbabilityHistoryData,
} from '@/components/user/default/market-probability-chart';
import MarketTopHolders from '@/components/user/default/market-top-holders';
import OutcomeList from '@/components/user/default/outcome-list';
import OutcomeProbability from '@/components/user/default/outcome-probability';
import RelatedMarkets from '@/components/user/default/related-markets';
import TradeForm from '@/components/user/default/trade-form';
import { useCurrency } from '@/hooks/use-currency';
import { useApiSWR } from '@/hooks/useSWR';
import { handleApiError } from '@/lib/error-handler';
import { request } from '@/lib/fetcher';
import {
  TMarket,
  TMarketOutcome,
  TMarketTrade,
  TOrderFill,
} from '@/types/market.types';
import { getImageUrl } from '@/utils/getImageUrl';
import { usePage } from '@inertiajs/react';
import {
  BookmarkIcon,
  BookmarkSimpleIcon,
  ChartLineUpIcon,
  ClockIcon,
  CopyIcon,
  TrophyIcon,
  XLogoIcon,
} from '@phosphor-icons/react';
import { SortingState } from '@tanstack/react-table';
import dayjs from 'dayjs';
import relativeTime from 'dayjs/plugin/relativeTime';
import { useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';

dayjs.extend(relativeTime);

const STATUS_VARIANT: Record<
  string,
  'warning' | 'destructive' | 'successSubtle'
> = {
  closed: 'warning',
  resolved: 'successSubtle',
  cancelled: 'destructive',
};

type TPageProps = { auth: { user: { id: number } | null } };

const Market = () => {
  const { t } = useTranslation();
  const { format } = useCurrency();
  const [sorting, setSorting] = useState<SortingState>([]);
  const [changes, setChanges] = useState<Record<number, number | null>>({});
  const [watchlistLoading, setWatchlistLoading] = useState(false);
  const [selectedOutcome, setSelectedOutcome] = useState<TMarketOutcome | null>(
    null,
  );
  const [tradeSide, setTradeSide] = useState<'buy' | 'sell'>('buy');
  // Bumped when a CLOB book level is clicked, to prefill the trade panel's price.
  const [clobPrefill, setClobPrefill] = useState({ price: '', n: 0 });

  const { auth } = usePage<TPageProps>().props;
  const isLoggedIn = !!auth?.user;

  const slug =
    usePage().url.split('?')[0].split('/').filter(Boolean).pop() ?? '';

  const {
    data: market,
    isLoading,
    mutate,
  } = useApiSWR<TMarket>(slug ? `/markets/${slug}` : null);

  const { data: tradesData, isLoading: tradesLoading } = useApiSWR<{
    data: TMarketTrade[];
  }>(slug ? `/markets/${slug}/trades?limit=20` : null);

  // CLOB markets record activity as order fills, not MarketTrade rows.
  const isClob = market?.engine === 'clob';
  const { data: fillsData, isLoading: fillsLoading } = useApiSWR<{
    data: TOrderFill[];
  }>(slug && isClob ? `/markets/${slug}/fills?limit=20` : null);

  // Keep the selected outcome in sync with freshly fetched market data:
  // default to the current leader, but preserve an existing user pick.
  useEffect(() => {
    if (!market) return;
    setSelectedOutcome((prev) => {
      if (prev) {
        const refreshed = market.outcomes.find((o) => o.id === prev.id);
        if (refreshed) return refreshed;
      }
      return (
        [...market.outcomes].sort(
          (a, b) => (b.probability ?? 0) - (a.probability ?? 0),
        )[0] ?? null
      );
    });
  }, [market]);

  // Honour a deep link from the browse cards (?outcome=<id>&side=buy) once the
  // market has loaded: preselect that outcome/side and reveal the trade widget.
  const deepLinkApplied = useRef(false);
  useEffect(() => {
    if (!market || deepLinkApplied.current) return;
    deepLinkApplied.current = true;
    const params = new URLSearchParams(window.location.search);
    const outcomeId = params.get('outcome');
    if (!outcomeId) return;
    const found = market.outcomes.find((o) => String(o.id) === outcomeId);
    if (!found) return;
    setSelectedOutcome(found);
    setTradeSide(params.get('side') === 'sell' ? 'sell' : 'buy');
    setTimeout(
      () =>
        document
          .getElementById('trade-widget')
          ?.scrollIntoView({ behavior: 'smooth', block: 'nearest' }),
      150,
    );
  }, [market]);

  // A Buy click in the candidate list drives the trade widget and, on mobile,
  // scrolls it into view.
  const handlePickOutcome = (outcome: TMarketOutcome) => {
    setSelectedOutcome(outcome);
    setTradeSide('buy');
    document
      .getElementById('trade-widget')
      ?.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  };

  const handleCopyLink = async () => {
    try {
      await navigator.clipboard.writeText(window.location.href);
      toast.success(t('Link copied!'));
    } catch {
      toast.error(t('Failed to copy link.'));
    }
  };

  const handleShareX = () => {
    if (!market) return;
    const url = encodeURIComponent(window.location.href);
    const text = encodeURIComponent(market.title);
    window.open(
      `https://x.com/intent/tweet?text=${text}&url=${url}`,
      '_blank',
      'noopener',
    );
  };

  const handleWatchlistToggle = async () => {
    if (!market) return;
    setWatchlistLoading(true);
    try {
      const res = await request.post<{ is_watched: boolean }>(
        `/api/user/markets/${slug}/watchlist`,
      );
      mutate({ ...market, is_watched: res.data.is_watched }, false);
      toast.success(
        res.data.is_watched
          ? t('Added to watchlist.')
          : t('Removed from watchlist.'),
      );
    } catch (err) {
      handleApiError(err);
    } finally {
      setWatchlistLoading(false);
    }
  };

  if (isLoading) {
    return (
      <div className="grid grid-cols-1 gap-4 lg:grid-cols-12">
        <div className="mb-4 space-y-4 lg:col-span-8">
          <div className="flex items-center gap-3 pt-2 pb-4">
            <div className="min-w-0 flex-1 space-y-2">
              <Skeleton className="h-3 w-24" />
              <Skeleton className="h-7 w-3/4 rounded-xl" />
              <div className="flex flex-wrap items-center gap-2 pt-1">
                <Skeleton className="h-5 w-16 rounded-full" />
                <Skeleton className="h-5 w-24 rounded-full" />
                <Skeleton className="h-5 w-28 rounded-full" />
              </div>
            </div>
            <div className="flex shrink-0 items-center gap-0.5">
              <Skeleton className="size-9 rounded-lg" />
              <Skeleton className="size-9 rounded-lg" />
            </div>
          </div>

          <Card className="rounded-2xl p-4 py-4 dark:border-white/8">
            <Skeleton className="h-56 w-full rounded-xl" />
            <div className="mt-4 space-y-2">
              <Skeleton className="h-10 w-full rounded-xl" />
              <Skeleton className="h-10 w-full rounded-xl" />
            </div>
          </Card>

          <Card className="gap-0 rounded-2xl p-0 dark:border-white/8">
            <div className="flex h-[62px] items-center px-6">
              <Skeleton className="h-5 w-32" />
            </div>
            <Separator className="bg-black/6 dark:bg-white/6" />
            <div className="space-y-3 p-6">
              {Array.from({ length: 5 }).map((_, i) => (
                <Skeleton key={i} className="h-8 w-full" />
              ))}
            </div>
          </Card>
        </div>

        <div className="space-y-4 lg:col-span-4 lg:self-start">
          <Card className="rounded-2xl p-4 py-4 dark:border-white/8">
            <Skeleton className="mb-4 h-5 w-28" />
            <Skeleton className="h-11 w-full rounded-2xl" />
            <div className="mt-4 space-y-2">
              <Skeleton className="h-12 w-full rounded-xl" />
              <Skeleton className="h-12 w-full rounded-xl" />
              <Skeleton className="h-12 w-full rounded-xl" />
            </div>
          </Card>

          <Card className="rounded-2xl p-4 py-4 dark:border-white/8">
            <Skeleton className="mb-4 h-5 w-24" />
            <div className="space-y-3">
              {Array.from({ length: 4 }).map((_, i) => (
                <div key={i} className="flex items-center gap-3">
                  <Skeleton className="size-8 rounded-full" />
                  <Skeleton className="h-4 flex-1" />
                </div>
              ))}
            </div>
          </Card>
        </div>
      </div>
    );
  }

  if (!market) {
    return (
      <div className="py-20 text-center text-black/40 dark:text-white/40">
        {t('Market not found.')}
      </div>
    );
  }

  const trades: TMarketTrade[] = isClob
    ? (fillsData?.data ?? []).map((f) => ({
        id: f.id,
        type: f.taker_side,
        shares: f.qty,
        price: f.price,
        amount: f.taker_amount,
        outcome: f.taker_outcome ?? { id: 0, title: '', color: null },
        created_at: f.created_at,
      }))
    : (tradesData?.data ?? []);
  const tradesBusy = isClob ? fillsLoading : tradesLoading;
  const statusVariant = STATUS_VARIANT[market.status];
  const winningOutcome = market.winning_outcome_id
    ? market.outcomes.find((o) => o.id === market.winning_outcome_id)
    : null;

  const imageUrl = market.image ? getImageUrl(market.image) : null;

  return (
    <div className="grid grid-cols-1 gap-4 lg:grid-cols-12">
      <div className="mb-4 space-y-4 lg:col-span-8">
        {imageUrl && (
          <div className="overflow-hidden rounded-2xl">
            <img
              src={imageUrl}
              alt={market.title}
              className="h-48 w-full object-cover"
            />
          </div>
        )}

        <div className="flex items-center gap-3 pt-2 pb-4">
          <div className="min-w-0 flex-1">
            <div className="mb-2">
              <div className="mb-1 text-xs font-semibold tracking-[0.09em] text-black/40 uppercase dark:text-white/40">
                {market.category?.name ?? t('Market')}
              </div>
              <h1 className="text-2xl leading-tight font-bold tracking-tight text-balance text-card-foreground">
                {market.title}
              </h1>
            </div>

            <div className="flex flex-wrap items-center gap-2">
              {statusVariant && (
                <Badge variant={statusVariant} className="capitalize">
                  {market?.status}
                </Badge>
              )}
              <span className="flex items-center gap-1 text-sm text-black/40 dark:text-white/40">
                <ChartLineUpIcon weight="bold" className="size-4" />
                {format(market?.total_volume)} {t('volume')}
              </span>
              <span className="flex items-center gap-1 text-sm text-black/40 dark:text-white/40">
                <ClockIcon weight="bold" className="size-4" />
                {market.status === 'open'
                  ? `${t('Closes')} ${dayjs(market.closes_at).fromNow()}`
                  : dayjs(market.closes_at).format('MMM D, YYYY')}
              </span>
            </div>
          </div>

          <div className="flex shrink-0 items-center gap-0.5">
            <EmbedDialog market={market} />
            <Button
              variant="icon"
              size="icon"
              onClick={handleCopyLink}
              title={t('Copy link')}
            >
              <CopyIcon className="size-5" />
            </Button>
            <Button
              variant="icon"
              size="icon"
              onClick={handleShareX}
              title={t('Share on X')}
            >
              <XLogoIcon className="size-5" />
            </Button>
            {isLoggedIn && (
              <Button
                variant="icon"
                size="icon"
                onClick={handleWatchlistToggle}
                disabled={watchlistLoading}
                title={
                  market.is_watched
                    ? t('Remove from watchlist')
                    : t('Add to watchlist')
                }
              >
                {market.is_watched ? (
                  <BookmarkSimpleIcon
                    weight="fill"
                    className="size-5 text-primary"
                  />
                ) : (
                  <BookmarkIcon weight="regular" className="size-5" />
                )}
              </Button>
            )}
          </div>
        </div>

        {winningOutcome && (
          <Card className="flex items-center gap-3 rounded-2xl border-pm-yes bg-pm-yes-soft p-4 py-4">
            <TrophyIcon weight="fill" className="size-6 shrink-0 text-pm-yes" />
            <div>
              <p className="text-xs font-light text-pm-yes-ink/70">
                {t('Resolved outcome')}
              </p>
              <p className="font-semibold text-pm-yes-ink">
                {winningOutcome.title}
              </p>
            </div>
          </Card>
        )}

        <Card className="rounded-2xl p-4 py-4 dark:border-white/8">
          <MarketProbabilityChart
            slug={slug}
            onData={(d: ProbabilityHistoryData) => setChanges(d.changes)}
          />
          <div className="mt-4">
            {market.type === 'multi' ? (
              <OutcomeList
                outcomes={market.outcomes}
                selectedId={selectedOutcome?.id}
                changes={changes}
                onPick={handlePickOutcome}
                disabled={market.status !== 'open'}
              />
            ) : (
              <OutcomeProbability
                outcomes={market.outcomes}
                size="md"
                changes={changes}
              />
            )}
          </div>
          {market.description && (
            <p className="mt-4 text-sm leading-relaxed text-black/50 dark:text-white/50">
              {market.description}
            </p>
          )}
        </Card>

        {isClob && market.status === 'open' && (
          <Card className="rounded-2xl p-4 py-4 dark:border-white/8">
            <ClobBook
              slug={slug}
              selected={selectedOutcome ?? market.outcomes[0]}
              onPickPrice={(p) =>
                setClobPrefill((s) => ({ price: String(p), n: s.n + 1 }))
              }
              changes={changes}
              onTraded={() => mutate()}
            />
          </Card>
        )}

        {market.rules && (
          <Card className="rounded-2xl p-0 px-4 dark:border-white/8">
            <Accordion type="single" collapsible>
              <AccordionItem value="rules" className="border-0 px-0">
                <AccordionTrigger className="text-sm font-semibold">
                  {t('Resolution Rules')}
                </AccordionTrigger>
                <AccordionContent>
                  <p className="text-sm leading-relaxed whitespace-pre-line text-black/70 dark:text-white/70">
                    {market.rules}
                  </p>
                </AccordionContent>
              </AccordionItem>
            </Accordion>
          </Card>
        )}

        <Card className="gap-0 rounded-2xl p-0 dark:border-white/8">
          <div className="flex h-[62px] items-center px-6">
            <h2 className="text-base font-semibold text-card-foreground">
              {t('Recent Trades')}
            </h2>
          </div>
          <Separator className="bg-black/6 dark:bg-white/6" />
          <DataTable
            data={trades}
            sorting={sorting}
            setSorting={setSorting}
            isLoading={tradesBusy}
            rounded={false}
            shadow={false}
            structure={[
              {
                accessorKey: 'outcome',
                header: t('Outcome'),
                cell: ({ row }) => (
                  <span
                    className="font-medium"
                    style={{ color: row.original.outcome?.color ?? undefined }}
                  >
                    {row.original.outcome?.title}
                  </span>
                ),
              },
              {
                accessorKey: 'type',
                header: t('Type'),
                cell: ({ row }) => (
                  <Badge
                    variant={
                      row.original.type === 'buy' ? 'success' : 'warning'
                    }
                    className="capitalize"
                  >
                    {row.original.type}
                  </Badge>
                ),
              },
              {
                accessorKey: 'shares',
                header: t('Shares'),
                cell: ({ row }) => Number(row.original.shares).toFixed(4),
              },
              {
                accessorKey: 'price',
                header: t('Price'),
                cell: ({ row }) => format(Number(row.original.price)),
              },
              {
                accessorKey: 'amount',
                header: t('Amount'),
                cell: ({ row }) => format(row.original.amount),
              },
              {
                accessorKey: 'created_at',
                header: t('Time'),
                cell: ({ row }) => (
                  <div>
                    <p className="text-sm">
                      {dayjs(row.original.created_at).format('MMM D, YYYY')}
                    </p>
                    <p className="text-xs text-black/40 dark:text-white/40">
                      {dayjs(row.original.created_at).fromNow()}
                    </p>
                  </div>
                ),
              },
            ]}
          />
        </Card>

        <Card className="rounded-2xl p-6 dark:border-white/8">
          <h2 className="mb-5 text-base font-semibold text-card-foreground">
            {t('Discussion')}
          </h2>
          <MarketComments slug={slug} />
        </Card>

        <RelatedMarkets slug={slug} />
      </div>

      <div
        id="trade-widget"
        className="scroll-mt-4 space-y-4 lg:sticky lg:top-4 lg:col-span-4 lg:self-start"
      >
        {market.status !== 'open' ? (
          <Card className="rounded-2xl p-4 py-4 dark:border-white/8">
            <h3 className="mb-2 text-base font-semibold text-card-foreground">
              {t('Place a Trade')}
            </h3>
            <p className="text-center text-sm text-black/40 dark:text-white/40">
              {t('Trading is closed for this market.')}
            </p>
          </Card>
        ) : isClob ? (
          <ClobTradePanel
            market={market}
            slug={slug}
            selected={selectedOutcome ?? market.outcomes[0]}
            onSelectOutcome={setSelectedOutcome}
            isLoggedIn={isLoggedIn}
            onTraded={() => mutate()}
            prefill={clobPrefill}
          />
        ) : (
          <TradeForm
            market={market}
            selectedOutcome={selectedOutcome ?? market.outcomes[0]}
            onSelectOutcome={setSelectedOutcome}
            side={tradeSide}
            onSideChange={setTradeSide}
            onTradeSuccess={() => mutate()}
          />
        )}

        <Card className="rounded-2xl p-4 py-4 dark:border-white/8">
          <h3 className="mb-2 text-base font-semibold text-card-foreground">
            {t('Top Holders')}
          </h3>
          <MarketTopHolders slug={slug} />
        </Card>
      </div>
    </div>
  );
};

Market.title = 'Market';

export default Market;
