import { ChevronDownIcon, InfoIcon } from "lucide-react";
import React from "react";
import { useNavigate } from "react-router";
import { toast } from "sonner";
import AppHeader from "src/components/AppHeader";
import ExternalLink from "src/components/ExternalLink";
import { FormattedBitcoinAmount } from "src/components/FormattedBitcoinAmount";
import Loading from "src/components/Loading";
import { Button } from "src/components/ui/button";
import { Checkbox } from "src/components/ui/checkbox";
import { LoadingButton } from "src/components/ui/custom/loading-button";
import { Label } from "src/components/ui/label";
import { Separator } from "src/components/ui/separator";
import { useChannels } from "src/hooks/useChannels";

import { useInfo } from "src/hooks/useInfo";
import {
  AutoChannelRequest,
  AutoChannelResponse,
  LSPChannelOfferPaymentMethod,
} from "src/types";
import { request } from "src/utils/request";

import { Invoice } from "@getalby/lightning-tools";
import { MempoolAlert } from "src/components/MempoolAlert";
import { PayLightningInvoice } from "src/components/PayLightningInvoice";
import { Table, TableBody, TableCell, TableRow } from "src/components/ui/table";

import LightningNetworkDarkSVG from "public/images/illustrations/lightning-network-dark.svg";
import LightningNetworkLightSVG from "public/images/illustrations/lightning-network-light.svg";
import { LSPTermsDialog } from "src/components/channels/LSPTermsDialog";
import FormattedFiatAmount from "src/components/FormattedFiatAmount";
import { ExternalLinkButton } from "src/components/ui/custom/external-link-button";
import { LinkButton } from "src/components/ui/custom/link-button";
import {
  Field,
  FieldContent,
  FieldLabel,
  FieldTitle,
} from "src/components/ui/field";
import { RadioGroup, RadioGroupItem } from "src/components/ui/radio-group";
import {
  Tooltip,
  TooltipContent,
  TooltipProvider,
  TooltipTrigger,
} from "src/components/ui/tooltip";
import { useLSPChannelOffer } from "src/hooks/useLSPChannelOffer";
import { cn } from "src/lib/utils";
import { openLink } from "src/utils/openLink";

export function FirstChannel() {
  const { data: info } = useInfo();
  const { data: channels } = useChannels(true);
  const [isLoading, setLoading] = React.useState(false);
  const [showAdvanced, setShowAdvanced] = React.useState(false);
  const [isPublic, setPublic] = React.useState(false);
  const { data: lspChannelOffer } = useLSPChannelOffer();

  const navigate = useNavigate();
  const [invoice, setInvoice] = React.useState<string>();
  const [channelSizeSat, setChannelSizeSat] = React.useState<number>();
  const [currentPaymentMethod, setCurrentPaymentMethod] =
    React.useState<LSPChannelOfferPaymentMethod>();

  React.useEffect(() => {
    if (channels?.length) {
      navigate("/channels/first/opening");
    }
  }, [channels, navigate]);

  React.useEffect(() => {
    if (info && !info.albyAccountConnected) {
      navigate("/channels/incoming");
    }
  }, [info, navigate]);

  if (!info?.albyAccountConnected || !channels || !lspChannelOffer) {
    return <Loading />;
  }

  async function openChannel() {
    if (!info || !channels || !lspChannelOffer) {
      return;
    }
    if (
      (lspChannelOffer.currentPaymentMethod === "card" ||
        lspChannelOffer.currentPaymentMethod === "wallet") &&
      currentPaymentMethod !== lspChannelOffer.currentPaymentMethod
    ) {
      toast.error("Payment method incorrectly configured", {
        description: currentPaymentMethod
          ? "Please switch the payment method and confirm the change in your Alby Account settings"
          : "Please choose a payment method",
      });
      return;
    }
    setLoading(true);
    try {
      const newInstantChannelInvoiceRequest: AutoChannelRequest = {
        isPublic,
      };
      const autoChannelResponse = await request<AutoChannelResponse>(
        "/api/alby/auto-channel",
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(newInstantChannelInvoiceRequest),
        }
      );
      if (!autoChannelResponse) {
        throw new Error("unexpected auto channel response");
      }

      setInvoice(autoChannelResponse.invoice);
      setChannelSizeSat(autoChannelResponse.channelSizeSat);
    } catch (error) {
      setLoading(false);
      console.error(error);
      toast.error("Something went wrong. Please try again");
    }
  }

  return (
    <>
      <AppHeader
        pageTitle="Open Your First Channel"
        title="Open Your First Channel"
        description="Open a channel to another lightning network node to join the lightning network"
      />
      <MempoolAlert />
      {invoice && channelSizeSat && (
        <div className="flex flex-col gap-4 items-center justify-center max-w-md">
          <p className="text-muted-foreground slashed-zero">
            Alby Hub works with selected service providers (LSPs) which provide
            the best network connectivity and liquidity to receive payments. To
            quickly get started you can buy a channel from an LSP by paying the
            lightning invoice below.
          </p>
          <div className="border rounded-lg slashed-zero w-full">
            <Table>
              <TableBody>
                <TableRow>
                  <TableCell className="font-medium p-3">
                    Incoming Liquidity
                  </TableCell>
                  <TableCell className="text-right p-3">
                    <FormattedBitcoinAmount
                      amountMsat={channelSizeSat * 1000}
                    />
                  </TableCell>
                </TableRow>
                {invoice && (
                  <TableRow>
                    <TableCell className="font-medium p-3">
                      Amount to pay
                    </TableCell>
                    <TableCell className="font-semibold text-right p-3">
                      <FormattedBitcoinAmount
                        amountMsat={new Invoice({ pr: invoice }).satoshi * 1000}
                      />
                    </TableCell>
                  </TableRow>
                )}
              </TableBody>
            </Table>
          </div>
          <PayLightningInvoice invoice={invoice} />

          <Separator className="mt-2" />
          <p className="mt-8 text-sm mb-2 text-muted-foreground">
            Other options
          </p>
          <LinkButton
            to="/channels/outgoing"
            variant="secondary"
            className="w-full"
          >
            Open Channel with On-Chain Bitcoin
          </LinkButton>
          <ExternalLinkButton
            to="https://www.getalby.com/topup"
            variant="secondary"
            className="w-full"
          >
            Buy Bitcoin
          </ExternalLinkButton>
        </div>
      )}
      {!invoice && (
        <>
          <div className="flex flex-col gap-6 max-w-md text-muted-foreground">
            <img
              src={LightningNetworkDarkSVG}
              className="w-full hidden dark:block"
            />
            <img
              src={LightningNetworkLightSVG}
              className="w-full dark:hidden"
            />
            <p>
              You're now going to open your first lightning channel and can
              begin using your Hub in the booming bitcoin economy!
            </p>
            <p className="text-muted-foreground">
              Alby Hub works with selected service providers (LSPs) which
              provide the best network connectivity and liquidity to receive
              payments.
            </p>
            <div>
              <h2 className="font-medium text-foreground mb-3">
                Purchase Your First Channel
              </h2>
              <p>
                A payment is required to purchase a channel from{" "}
                <ExternalLink
                  to={lspChannelOffer.lspContactUrl}
                  className="underline"
                >
                  {lspChannelOffer.lspName}
                </ExternalLink>
                . Once your channel is opened, you'll immediately be able to
                receive and send bitcoin with your Hub.
              </p>
            </div>

            {lspChannelOffer.currentPaymentMethod !== "prepaid" &&
              lspChannelOffer.currentPaymentMethod !== "included" && (
                <div>
                  <h3 className="font-medium text-sm text-foreground mb-3">
                    Payment method
                  </h3>
                  <RadioGroup
                    value={currentPaymentMethod}
                    onValueChange={(
                      newPaymentMethod: LSPChannelOfferPaymentMethod
                    ) => {
                      if (
                        newPaymentMethod !==
                        lspChannelOffer.currentPaymentMethod
                      ) {
                        openLink("https://getalby.com/payment_details");
                      }
                      setCurrentPaymentMethod(newPaymentMethod);
                    }}
                  >
                    <FieldLabel htmlFor="wallet">
                      <Field orientation="horizontal">
                        <RadioGroupItem
                          value={
                            "wallet" satisfies LSPChannelOfferPaymentMethod
                          }
                          id="wallet"
                        />
                        <FieldContent>
                          <FieldTitle>Bitcoin</FieldTitle>
                        </FieldContent>
                      </Field>
                    </FieldLabel>
                    <FieldLabel htmlFor="card">
                      <Field orientation="horizontal">
                        <RadioGroupItem
                          value={"card" satisfies LSPChannelOfferPaymentMethod}
                          id="card"
                        />
                        <FieldContent>
                          <FieldTitle>Credit / Debit Card</FieldTitle>
                        </FieldContent>
                      </Field>
                    </FieldLabel>
                  </RadioGroup>
                </div>
              )}
            {showAdvanced && (
              <>
                <div className="mt-2 flex items-top space-x-2">
                  <Checkbox
                    id="public-channel"
                    onCheckedChange={() => setPublic(!isPublic)}
                    className="mr-2"
                  />
                  <div className="grid gap-1.5 leading-none">
                    <Label
                      htmlFor="public-channel"
                      className="cursor-pointer text-foreground"
                    >
                      Public Channel
                    </Label>
                    <p className="text-xs text-muted-foreground">
                      Not recommended for most users.{" "}
                      <ExternalLink
                        className="underline"
                        to="https://guides.getalby.com/user-guide/alby-hub/faq/should-i-open-a-private-or-public-channel"
                      >
                        Learn more
                      </ExternalLink>
                    </p>
                  </div>
                </div>
              </>
            )}
            {!showAdvanced && (
              <div>
                <Button
                  type="button"
                  variant="link"
                  className="text-muted-foreground text-xs px-0"
                  onClick={() => setShowAdvanced((current) => !current)}
                >
                  Advanced Options
                  <ChevronDownIcon className="size-4" />
                </Button>
              </div>
            )}

            <Separator />

            <Table>
              <TableBody>
                <TableRow className="border-0">
                  <TableCell className="px-3 align-top">
                    <div className="flex flex-1 items-center gap-1 text-sm">
                      You'll be able to receive up to{" "}
                      <TooltipProvider>
                        <Tooltip>
                          <TooltipTrigger>
                            <div className="flex flex-row items-center">
                              <InfoIcon className="h-4 w-4 shrink-0 text-muted-foreground" />
                            </div>
                          </TooltipTrigger>
                          <TooltipContent className="max-w-sm">
                            The amount you will be able to receive when funds
                            are on your counterparty's side of the channel.
                          </TooltipContent>
                        </Tooltip>
                      </TooltipProvider>
                    </div>
                  </TableCell>
                  <TableCell className="px-3 flex flex-col gap-2 items-end justify-center align-top">
                    {/* <span>
                      <FormattedBitcoinAmount
                        amountMsat={lspChannelOffer.lspBalanceSat * 1000}
                      />
                    </span> */}
                    <FormattedFiatAmount
                      amountSat={lspChannelOffer.lspBalanceSat}
                      showApprox
                    />
                  </TableCell>
                </TableRow>
                <TableRow className="border-0">
                  <TableCell className="p-3 text-sm">
                    Channel Cost
                    {lspChannelOffer.currentPaymentMethod === "included" &&
                      " (Included in your plan)"}
                  </TableCell>
                  <TableCell className="p-3 flex flex-col gap-2 items-end justify-center">
                    <p>
                      <span
                        className={cn(
                          lspChannelOffer.currentPaymentMethod === "included" &&
                            "line-through"
                        )}
                      >
                        {new Intl.NumberFormat(undefined, {
                          style: "currency",
                          currency: "USD",
                        }).format(lspChannelOffer.feeTotalUsd / 100)}
                      </span>
                      {lspChannelOffer.currentPaymentMethod === "included" && (
                        <span> $0.00</span>
                      )}
                    </p>
                  </TableCell>
                </TableRow>
              </TableBody>
            </Table>

            <div className="w-full flex items-center justify-center -mb-2">
              <p className="text-center text-xs max-w-md">
                By continuing, you consent to the{" "}
                <LSPTermsDialog
                  contactUrl={lspChannelOffer.lspContactUrl}
                  description={lspChannelOffer.lspDescription}
                  name={lspChannelOffer.lspName}
                  terms={lspChannelOffer.terms}
                  trigger={<span className="underline">LSP terms</span>}
                />{" "}
                and that the channel opens immediately and that you lose the
                right to revoke once it is open.
              </p>
            </div>

            <LoadingButton loading={isLoading} onClick={openChannel}>
              {lspChannelOffer.currentPaymentMethod === "prepaid" ? (
                <>Review Order</>
              ) : lspChannelOffer.currentPaymentMethod === "included" ? (
                <>Open Channel</>
              ) : (
                <>
                  Pay{" "}
                  {new Intl.NumberFormat(undefined, {
                    style: "currency",
                    currency: "USD",
                  }).format(lspChannelOffer.feeTotalUsd / 100)}{" "}
                  and Open Channel
                </>
              )}
            </LoadingButton>
          </div>
        </>
      )}
    </>
  );
}
