import { Button } from '@/components/ui/button';
import { Card } from '@/components/ui/card';
import { createRequest } from '@/data/request/create-request';
import { useCurrency } from '@/hooks/use-currency';
import { cn } from '@/lib/utils';
import type { SharedData } from '@/types';
import { TMarket, TMarketOutcome } from '@/types/market.types';
import { getImageUrl } from '@/utils/getImageUrl';
import { usePage } from '@inertiajs/react';
import { TrendUpIcon } from '@phosphor-icons/react';
import { useMemo, useState, useTransition } from 'react';
import { useTranslation } from 'react-i18next';
import { toast } from 'sonner';

const DEFAULT_COLORS = ['#22c55e', '#ef4444', '#3b82f6', '#a855f7'];

type Side = 'buy' | 'sell';

interface TradeFormProps {
  market: TMarket;
  selectedOutcome: TMarketOutcome;
  onSelectOutcome: (outcome: TMarketOutcome) => void;
  side: Side;
  onSideChange: (side: Side) => void;
  onTradeSuccess?: () => void;
}

// Quick-add chip presets: dollars when buying, share counts when selling.
const BUY_STEPS = [1, 5, 10, 100];
const SELL_STEPS = [1, 5, 10, 100];

export default function TradeForm({
  market,
  selectedOutcome,
  onSelectOutcome,
  side,
  onSideChange,
  onTradeSuccess,
}: TradeFormProps) {
  const { t } = useTranslation();
  const { format } = useCurrency();
  const { branding } = usePage<SharedData>().props;

  // Admin-configured trade commission (percent → fraction).
  const feePercent = branding?.trading?.trade_commission_percent ?? 0;
  const feeRate = feePercent / 100;

  const [amount, setAmount] = useState('');
  const [shares, setShares] = useState('');
  const [isPending, startTransition] = useTransition();

  // Extract the currency symbol from a formatted zero (e.g. "$0.00" -> "$").
  const symbol = useMemo(
    () => format(0).replace(/[\d\s.,]/g, '') || '$',
    [format],
  );

  const outcomeColor = (o: TMarketOutcome, i: number) =>
    o.color ?? DEFAULT_COLORS[i % DEFAULT_COLORS.length];

  const selectedIndex = market.outcomes.findIndex(
    (o) => o.id === selectedOutcome.id,
  );
  const selColor = outcomeColor(selectedOutcome, Math.max(selectedIndex, 0));

  const price = selectedOutcome?.probability ?? 0.5;
  const amountNum = Number(amount) || 0;
  const sharesNum = Number(shares) || 0;

  // Commission is skimmed from the trade value: off the spend when buying, off
  // the proceeds when selling. Mirrors MarketService (server-side authority).
  const buyFee = amountNum * feeRate;
  const buyNet = amountNum - buyFee;
  // Buying (net of fee) at price p yields net / p shares, each worth $1 if it wins.
  const buyShares = price > 0 ? buyNet / price : 0;

  const sellGross = sharesNum * price;
  const sellFee = sellGross * feeRate;
  const sellNet = sellGross - sellFee;

  const fee = side === 'buy' ? buyFee : sellFee;
  const toWin = side === 'buy' ? buyShares : sellNet;
  const hasValue = side === 'buy' ? amountNum > 0 : sharesNum > 0;

  const handleStep = (v: number) => {
    if (side === 'buy') {
      setAmount((prev) => String((Number(prev) || 0) + v));
    } else {
      setShares((prev) => String((Number(prev) || 0) + v));
    }
  };

  const handleSubmit = () => {
    if (side === 'buy' && amountNum <= 0) {
      toast.error(t('Enter an amount to trade.'));
      return;
    }
    if (side === 'sell' && sharesNum <= 0) {
      toast.error(t('Enter the number of shares to sell.'));
      return;
    }

    startTransition(async () => {
      const result = await createRequest({
        url:
          side === 'buy'
            ? `/api/user/markets/${market.slug}/buy`
            : `/api/user/markets/${market.slug}/sell`,
        formData:
          side === 'buy'
            ? { outcome_id: selectedOutcome.id, amount: amountNum }
            : { outcome_id: selectedOutcome.id, shares: sharesNum },
      });

      if (result) {
        toast.success(
          side === 'buy'
            ? t('Trade executed successfully.')
            : t('Shares sold successfully.'),
        );
        setAmount('');
        setShares('');
        onTradeSuccess?.();
      }
    });
  };

  const steps = side === 'buy' ? BUY_STEPS : SELL_STEPS;

  return (
    <Card className="gap-0 overflow-hidden rounded-2xl p-0 dark:border-white/8">
      {/* Market header */}
      <div className="flex items-center gap-3 p-4">
        <div className="size-10 shrink-0 overflow-hidden rounded-md bg-secondary">
          {market.image ? (
            <img
              src={getImageUrl(market.image)}
              alt={market.title}
              className="size-full object-cover"
            />
          ) : (
            <div className="flex size-full items-center justify-center text-black/30 dark:text-white/30">
              <TrendUpIcon weight="bold" className="size-5" />
            </div>
          )}
        </div>
        <div className="min-w-0">
          <p className="truncate text-xs text-black/50 dark:text-white/50">
            {market.title}
          </p>
          <p className="text-sm font-semibold">
            {selectedOutcome.title}
            <span style={{ color: selColor }}>
              {' · '}
              {side === 'buy' ? t('Buy') : t('Sell')}
            </span>
          </p>
        </div>
      </div>

      {/* Side tabs */}
      <div className="flex items-center gap-4 border-b border-black/8 px-4 dark:border-white/8">
        {(['buy', 'sell'] as Side[]).map((s) => (
          <button
            key={s}
            type="button"
            onClick={() => onSideChange(s)}
            className={cn(
              'cursor-pointer border-b-2 pt-1 pb-2.5 text-sm font-semibold capitalize transition-colors',
              side === s
                ? 'border-foreground text-foreground'
                : 'border-transparent text-black/40 hover:text-black/60 dark:text-white/40 dark:hover:text-white/60',
            )}
          >
            {s === 'buy' ? t('Buy') : t('Sell')}
          </button>
        ))}
      </div>

      {/* Body */}
      <div className="space-y-5 p-4">
        {/* Outcome selector — binary markets pick here; multi-outcome markets
            pick from the candidate list and show the selection as a chip. */}
        {market.type === 'binary' ? (
          <div className="grid grid-cols-2 gap-2.5">
            {market.outcomes.map((outcome, i) => {
              const color = outcomeColor(outcome, i);
              const isSelected = selectedOutcome.id === outcome.id;
              return (
                <button
                  key={outcome.id}
                  type="button"
                  onClick={() => onSelectOutcome(outcome)}
                  className={cn(
                    'flex cursor-pointer items-center justify-center gap-1.5 rounded-lg px-3 py-3 text-sm font-bold transition-all',
                    isSelected
                      ? 'text-white'
                      : 'bg-secondary text-foreground hover:bg-black/8 dark:hover:bg-white/10',
                  )}
                  style={isSelected ? { backgroundColor: color } : undefined}
                >
                  <span>{outcome.title}</span>
                  <span className={isSelected ? 'text-white/90' : 'opacity-70'}>
                    {format(outcome.probability ?? 0)}
                  </span>
                </button>
              );
            })}
          </div>
        ) : (
          <div
            className="flex items-center justify-between rounded-lg px-3 py-3 text-sm font-bold text-white"
            style={{ backgroundColor: selColor }}
          >
            <span className="truncate">{selectedOutcome.title}</span>
            <span className="text-white/90">
              {format(selectedOutcome.probability ?? 0)}
            </span>
          </div>
        )}

        {/* Amount / Shares */}
        <div className="space-y-3">
          <div className="flex items-center justify-between">
            <span className="text-lg font-medium">
              {side === 'buy' ? t('Amount') : t('Shares')}
            </span>
            <div className="flex items-center gap-0.5 text-4xl leading-none font-bold">
              {side === 'buy' && (
                <span
                  className={
                    hasValue
                      ? 'text-black/80 dark:text-white/80'
                      : 'text-black/20 dark:text-white/20'
                  }
                >
                  {symbol}
                </span>
              )}
              <input
                inputMode="decimal"
                value={side === 'buy' ? amount : shares}
                onChange={(e) => {
                  const v = e.target.value.replace(/[^\d.]/g, '');
                  if (side === 'buy') setAmount(v);
                  else setShares(v);
                }}
                placeholder="0"
                style={{
                  width: `${Math.max((side === 'buy' ? amount : shares).length, 1)}ch`,
                }}
                className="bg-transparent text-right outline-none placeholder:text-black/20 dark:placeholder:text-white/20"
              />
            </div>
          </div>

          {/* Quick-add chips */}
          <div className="flex justify-end gap-2">
            {steps.map((v) => (
              <button
                key={v}
                type="button"
                onClick={() => handleStep(v)}
                className="cursor-pointer rounded-md border border-black/10 px-2.5 py-1 text-sm font-medium text-black/70 transition-colors hover:border-black/20 hover:bg-black/5 dark:border-white/15 dark:text-white/70 dark:hover:bg-white/5"
              >
                +{side === 'buy' ? `${symbol}${v}` : v}
              </button>
            ))}
          </div>
        </div>
      </div>

      {/* Footer: payout (only once an amount is entered) + submit */}
      <div className="space-y-4 p-4 pt-0">
        {hasValue && (
          <div className="space-y-2 border-t border-black/8 pt-4 dark:border-white/8">
            {fee > 0 && (
              <div className="flex items-center justify-between text-xs text-black/40 dark:text-white/40">
                <span>
                  {t('Commission')} ({feePercent}%)
                </span>
                <span>-{format(fee)}</span>
              </div>
            )}
            <div className="flex items-end justify-between">
              <div>
                <p className="flex items-center gap-1.5 text-base font-semibold">
                  {side === 'buy' ? t('To win') : t('You receive')}
                  <span aria-hidden>💵</span>
                </p>
                <p className="text-xs text-black/40 dark:text-white/40">
                  {t('Avg. Price')} {format(price)}
                </p>
              </div>
              <p className="text-3xl leading-none font-bold text-success">
                {format(toWin)}
              </p>
            </div>
          </div>
        )}

        <Button
          variant="primary"
          type="button"
          onClick={handleSubmit}
          loading={isPending}
          className="h-12 w-full rounded-xl text-base font-semibold"
        >
          {t('Trade')}
        </Button>
      </div>
    </Card>
  );
}
