import { CheckBoxOutlineBlank, CheckBoxOutlined } from "@mui/icons-material";
import { Box, Checkbox, FormControlLabel } from "@mui/material";
import { useState, useMemo } from "react";
import { useLocation } from "react-router-dom";

import { BOND_DEPOSITORY_ADDRESSES } from "../../../constants/addresses";
import { shorten, formatNumber, formatCurrency } from "../../../helpers";
import { DecimalBigNumber } from "../../../helpers/DecimalBigNumber";

import BondDiscount from "./BondDiscount";
import BondVesting from "./BondVesting";
import BondConfirmModal from "./BondConfirmModal";

import { TokenAllowanceGuard } from "../../../components/TokenAllowanceGuard/TokenAllowanceGuard";
import { PrimaryButton } from "../../../components/Button";
import SwapCard from "../../../components/Swap/SwapCard";
import SwapCollection from "../../../components/Swap/SwapCollection";
import TokenStack from "../../../components/TokenStack/TokenStack";
import DataRow from "../../../components/DataRow/DataRow";
import Paper from "../../../components/Paper/Paper";

import { useCurrentIndex } from "../../../hooks/staking";
import { useBalance } from "../../../hooks/tokens";

const BondInputArea = ({
    bond,
    chainId,
    slippage,
    recipientAddress,
    formatDecimals,
    handleSettingsOpen,
    address,
    connect
}) => {
    const { pathname } = useLocation();

    const { currentIndex } = useCurrentIndex(chainId);
    const { balance } = useBalance(chainId, bond.quoteToken.quoteTokenAddress, address);

    const { symbol: ftsoSymbol } = useTokenSymbol(chainId, "FTSO");
    const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");

    const [amount, setAmount] = useState("");
    const [checked, setChecked] = useState(false);
    const [confirmOpen, setConfirmOpen] = useState(false);

    const parsedAmount = useMemo(() => {
        return new DecimalBigNumber(amount, bond.quoteToken.decimals);
    }, [bond, amount])

    const amountInBaseToken = useMemo(() => {
        if (bond.price.inBaseToken._value !== 0n) return parsedAmount.div(bond.price.inBaseToken);
        return new DecimalBigNumber(0n, 0);
    }, [parsedAmount]);

    const showDisclaimer = useMemo(() => {
        return new DecimalBigNumber("0").gt(bond.discount);
    }, [bond]);

    const handleConfirmClose = () => {
        setAmount("");
        setConfirmOpen(false);
    }

    const setMax = () => {
        if (!balance) return;

        if (bond.capacity.inQuoteToken.lt(bond.maxPayout.inQuoteToken)) {
            return setAmount(
                bond.capacity.inQuoteToken.lt(balance)
                ? bond.capacity.inQuoteToken.toString() // Capacity is the smallest
                : balance.toString(),
            );
        }

        setAmount(
            bond.maxPayout.inQuoteToken.lt(balance)
            ? bond.maxPayout.inQuoteToken.toString() // Payout is the smallest
            : balance.toString(),
        );
    };

    const baseTokenString = (bond.maxPayout.inBaseToken.lt(bond.capacity.inBaseToken)
        ? bond.maxPayout.inBaseToken
        : bond.capacity.inBaseToken
    );

    return (
        <Box minHeight="calc(100vh - 210px)" display="flex" flexDirection="column" justifyContent="center">
            <Box display="flex" flexDirection="row" width="100%" justifyContent="center" mt="10px">
                <Box display="flex" flexDirection="column" width="100%" maxWidth="476px">
                    <Box mb="21px">
                        <SwapCollection
                            UpperSwapCard={
                                <SwapCard
                                    maxWidth="476px"
                                    inputWidth="280px"
                                    id="from"
                                    token={<TokenStack tokens={bond.quoteToken.icons} sx={{ fontSize: "21px" }} />}
                                    tokenName={bond.quoteToken.name}
                                    info={formatCurrency(balance, formatDecimals, bond.quoteToken.name)}
                                    endString="Max"
                                    endStringOnClick={setMax}
                                    value={amount}
                                    onChange={event => setAmount(event.currentTarget.value)}
                                    inputProps={{ "data-testid": "fromInput" }}
                                />
                                }
                                LowerSwapCard={
                                    <SwapCard
                                        maxWidth="476px"
                                        inputWidth="280px"
                                        id="to"
                                        token={<TokenStack tokens={bond.baseToken.icons} sx={{ fontSize: "21px" }} />}
                                        tokenName={bond.baseToken.name}
                                        value={amountInBaseToken.toString({ decimals: 9 })}
                                        inputProps={{ "data-testid": "toInput" }}
                                    />
                                }
                            />
                        </Box>

                        <TokenAllowanceGuard
                            spendAmount={parsedAmount}
                            tokenName={bond.quoteToken.quoteTokenAddress}
                            owner={address}
                            spender={BOND_DEPOSITORY_ADDRESSES[chainId]}
                            decimals={parsedAmount._decimals}
                            approvalText={`Approve ${bond.quoteToken.name} to Bond`}
                            approvalPendingText={"Approving..."}
                            connect={connect}
                            width="100%"
                            height="60px"
                            isVertical
                            message={
                                <>
                                    First time bonding <b>{bond.quoteToken.name}</b>? <br /> Please approve ghostDAO to use your{" "}
                                    <b>{bond.quoteToken.name}</b> for bonding.
                                </>
                            }
                        >
                            {showDisclaimer && (
                                <FormControlLabel
                                    control={
                                        <Checkbox
                                            checked={checked}
                                            onChange={event => setChecked(event.target.checked)}
                                            icon={<CheckBoxOutlineBlank viewBox="0 0 24 24" />}
                                            checkedIcon={<CheckBoxOutlined viewBox="0 0 24 24" />}
                                        />
                                    }
                                    label="I understand that I'm buying a negative discount bond"
                                />
                            )}
                            <PrimaryButton
                                fullWidth
                                disabled={bond.isSoldOut  || (showDisclaimer && !checked)}
                                onClick={() => setConfirmOpen(true)}
                            >
                                Bond
                            </PrimaryButton>
                        </TokenAllowanceGuard>

                        <Paper style={{ marginBottom: "7px", marginTop: "21px" }} fullWidth enableBackground>
                            <Box mt="24px">
                                <DataRow
                                    title={"You Will Get"}
                                    balance={
                                        <span>
                                            {formatCurrency(amountInBaseToken, formatDecimals, ftsoSymbol)}
                                            {" "}
                                            {!!currentIndex && (
                                                <span>
                                                    (≈{formatCurrency(amountInBaseToken.div(currentIndex), formatDecimals, ghstSymbol)})
                                                </span>
                                            )}
                                        </span>
                                    }
                                    tooltip={`The total amount of payout asset you will receive from this bond purchase`}
                                />

                                <DataRow
                                    title="Max You Can Buy"
                                    tooltip={`The maximum quantity of payout token offered via bonds at this moment in time`}
                                    balance={
                                        <span>
                                            {bond.baseToken.tokenAddress.toUpperCase() === bond.quoteToken.quoteTokenAddress.toUpperCase()
                                                ? `${formatCurrency(baseTokenString, formatDecimals, ftsoSymbol)}`
                                                : `${formatCurrency(baseTokenString, formatDecimals, ftsoSymbol)} (≈${formatCurrency(baseTokenString.div(currentIndex), formatDecimals, ghstSymbol)})`}
                                            </span>
                                        }
                                    />

                                <DataRow
                                    title="Discount"
                                    balance={<BondDiscount discount={bond.discount} textOnly />}
                                    tooltip={`The bond discount is the percentage difference between ${ftsoSymbol} market value and the bond's price`}
                                    />

                                <DataRow
                                    title={`Vesting Term`}
                                    balance={<BondVesting vesting={bond.vesting} />}
                                    tooltip={"The duration of the Bond whereby the bond can be claimed in its entirety"}
                                    />

                                {recipientAddress !== address && (
                                    <DataRow title={`Recipient`} balance={shorten(recipientAddress)} />
                                )}
                            </Box>
                        </Paper>
                    </Box>
                </Box>
                <BondConfirmModal
                    chainId={chainId}
                    bond={bond}
                    slippage={slippage}
                    recipientAddress={recipientAddress}
                    spendAmountValue={parsedAmount}
                    spendAmount={formatNumber(parsedAmount, formatDecimals)}
                    receiveAmount={formatNumber(amountInBaseToken, formatDecimals)}
                    handleSettingsOpen={handleSettingsOpen}
                    isOpen={confirmOpen}
                    handleConfirmClose={() => handleConfirmClose()}
                />
            </Box>
        );
    };

export default BondInputArea;
