import {
  CopyIcon,
  CreditCardIcon,
  ExternalLinkIcon,
  RefreshCwIcon,
} from "lucide-react";
import { useEffect, useRef, useState } from "react";
import AppHeader from "src/components/AppHeader";
import { FixedFloatButton } from "src/components/FixedFloatButton";
import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
import Loading from "src/components/Loading";
import LottieLoading from "src/components/LottieLoading";
import LottieSuccess from "src/components/LottieSuccess";
import { MempoolAlert } from "src/components/MempoolAlert";
import OnchainAddressDisplay from "src/components/OnchainAddressDisplay";
import QRCode from "src/components/QRCode";
import ResponsiveLinkButton from "src/components/ResponsiveLinkButton";
import { Button } from "src/components/ui/button";
import {
  Card,
  CardContent,
  CardHeader,
  CardTitle,
} from "src/components/ui/card";
import { ExternalLinkButton } from "src/components/ui/custom/external-link-button";
import { LinkButton } from "src/components/ui/custom/link-button";
import { LoadingButton } from "src/components/ui/custom/loading-button";
import { Separator } from "src/components/ui/separator";
import { useInfo } from "src/hooks/useInfo";
import { useMempoolApi } from "src/hooks/useMempoolApi";
import { useOnchainAddress } from "src/hooks/useOnchainAddress";
import { useSyncWallet } from "src/hooks/useSyncWallet";
import { copyToClipboard } from "src/lib/clipboard";
import { MempoolUtxo } from "src/types";

export default function DepositBitcoin() {
  useSyncWallet();
  const {
    data: onchainAddress,
    getNewAddress,
    loadingAddress,
  } = useOnchainAddress();
  const { data: mempoolAddressUtxos } = useMempoolApi<MempoolUtxo[]>(
    onchainAddress ? `/address/${onchainAddress}/utxo` : undefined,
    3000
  );
  const [txId, setTxId] = useState("");
  const [confirmedAmountSat, setConfirmedAmountSat] = useState<number | null>(
    null
  );
  const [pendingAmountSat, setPendingAmountSat] = useState<number | null>(null);
  const startTimeRef = useRef(0);

  useEffect(() => {
    if (startTimeRef.current === 0) {
      startTimeRef.current = Math.floor(Date.now() / 1000);
    }
  }, []);

  useEffect(() => {
    if (
      !mempoolAddressUtxos ||
      mempoolAddressUtxos.length === 0 ||
      startTimeRef.current === 0
    ) {
      return;
    }

    if (txId) {
      const utxo = mempoolAddressUtxos.find((utxo) => utxo.txid === txId);
      if (utxo?.status.confirmed) {
        setConfirmedAmountSat(utxo.value);
        setPendingAmountSat(null);
      }
    } else {
      const unconfirmed = mempoolAddressUtxos.find(
        (utxo) => !utxo.status.confirmed
      );
      if (unconfirmed) {
        setTxId(unconfirmed.txid);
        setPendingAmountSat(unconfirmed.value);
        return;
      }

      const confirmed = mempoolAddressUtxos.find(
        (utxo) =>
          utxo.status.confirmed &&
          !!utxo.status.block_time &&
          utxo.status.block_time >= startTimeRef.current
      );
      if (confirmed) {
        setTxId(confirmed.txid);
        setConfirmedAmountSat(confirmed.value);
        setPendingAmountSat(null);
      }
    }
  }, [mempoolAddressUtxos, txId]);

  if (!onchainAddress) {
    return <Loading />;
  }

  return (
    <div className="grid gap-5">
      <AppHeader
        pageTitle="Deposit Bitcoin to On-Chain Balance"
        title="Deposit Bitcoin to On-Chain Balance"
        description="Deposit bitcoin to your on-chain address which then can be used to open new lightning channels."
        contentRight={
          <ResponsiveLinkButton
            icon={CreditCardIcon}
            text="Buy Bitcoin"
            to="/channels/onchain/buy-bitcoin"
          />
        }
      />
      <MempoolAlert />
      <div className="w-80">
        {confirmedAmountSat ? (
          <DepositSuccess amountSat={confirmedAmountSat} txId={txId} />
        ) : txId ? (
          <DepositPending amountSat={pendingAmountSat} txId={txId} />
        ) : (
          <Card>
            <CardContent className="grid gap-6 justify-center">
              <a
                href={`bitcoin:${onchainAddress}`}
                target="_blank"
                className="flex justify-center"
              >
                <QRCode value={onchainAddress} paymentType="onchain" />
              </a>

              <div className="flex flex-wrap gap-2 items-center justify-center">
                <OnchainAddressDisplay address={onchainAddress} />
              </div>

              <div className="flex flex-col">
                <div className="flex w-full flex-col gap-3">
                  <LoadingButton
                    variant="outline"
                    onClick={getNewAddress}
                    className="w-full"
                    loading={loadingAddress}
                  >
                    {!loadingAddress && <RefreshCwIcon />}
                    Change
                  </LoadingButton>
                  <Button
                    variant="secondary"
                    className="w-full"
                    onClick={() => {
                      copyToClipboard(onchainAddress);
                    }}
                  >
                    <CopyIcon />
                    Copy
                  </Button>
                </div>
                <Separator className="my-4" />
                <FixedFloatButton
                  to="BTC"
                  address={onchainAddress}
                  className="w-full"
                  variant="outline"
                >
                  <ExternalLinkIcon className="size-4" />
                  Top Up with Crypto
                </FixedFloatButton>
              </div>
            </CardContent>
          </Card>
        )}
      </div>
    </div>
  );
}

function DepositPending({
  amountSat,
  txId,
}: {
  amountSat: number | null;
  txId: string;
}) {
  const { data: info } = useInfo();

  return (
    <Card className="w-full">
      <CardHeader>
        <CardTitle className="text-center">Awaiting Confirmation</CardTitle>
      </CardHeader>
      <CardContent className="flex flex-col items-center gap-4">
        <LottieLoading size={288} />
        {amountSat && (
          <div className="flex flex-col gap-2 items-center">
            <p className="text-xl font-semibold slashed-zero">
              <FormattedBitcoinAmount amountMsat={amountSat * 1000} />
            </p>
            <FormattedFiatAmount amountSat={amountSat} />
          </div>
        )}
        <div className="w-full">
          <ExternalLinkButton
            to={`${info?.mempoolUrl}/tx/${txId}`}
            variant="outline"
            className="mt-2 w-full"
          >
            View on Mempool
            <ExternalLinkIcon className="size-4" />
          </ExternalLinkButton>
        </div>
      </CardContent>
    </Card>
  );
}

function DepositSuccess({
  amountSat,
  txId,
}: {
  amountSat: number;
  txId: string;
}) {
  const { data: info } = useInfo();

  return (
    <>
      <Card className="w-full">
        <CardHeader>
          <CardTitle className="text-center">Payment Received!</CardTitle>
        </CardHeader>
        <CardContent className="flex flex-col items-center gap-4">
          <LottieSuccess />
          <div className="flex flex-col gap-2 items-center">
            <p className="text-xl font-semibold slashed-zero">
              <FormattedBitcoinAmount amountMsat={amountSat * 1000} />
            </p>
            <FormattedFiatAmount amountSat={amountSat} />
          </div>
          <div className="w-full">
            <ExternalLinkButton
              to={`${info?.mempoolUrl}/tx/${txId}`}
              variant="outline"
              className="mt-2 w-full"
            >
              View on Mempool
              <ExternalLinkIcon className="size-4" />
            </ExternalLinkButton>
          </div>
        </CardContent>
      </Card>
      <LinkButton to="/channels" className="mt-4 w-full">
        Back To Node
      </LinkButton>
    </>
  );
}
