import { useMemo, useState, useEffect } from "react";
import {
    Box,
    Typography,
    Link,
    Skeleton,
    TableContainer,
    Table,
    Paper,
    TableHead,
    TableBody,
    TableRow,
    TableCell,
    Modal,
    useTheme,
    useMediaQuery,
} from "@mui/material";

import { useConfig } from "wagmi";
import { ss58Decode } from "@polkadot-labs/hdkd-helpers";
import { toHex } from "@polkadot-api/utils";

import { PrimaryButton } from "../../components/Button";
import GhostStyledIcon from "../../components/Icon/GhostIcon";
import SwapCard from "../../components/Swap/SwapCard";
import SwapCollection from "../../components/Swap/SwapCollection";

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

import CheckIcon from '@mui/icons-material/Check';
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';

import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { formatNumber, formatCurrency, timeConverter } from "../../helpers";

import { BridgeRoute } from "./BridgeRoute";

const sliceString = (string, first, second) => {
    if (!string) return "";
    return string.slice(0, first) + "..." + string.slice(second);
}

export const BridgeCardAction = ({
    isVerySmallScreen,
    isSemiSmallScreen,
    chainId,
    address,
    ghstSymbol,
    gatekeeperAddressEmpty,
    gatekeeperAddress,
    evmNetwork,
    connect,
    isConfirmed,
    setIsConfirmed,
    openBridgeModal,
    storeTransactionHash,
}) => {
    const [isPending, setIsPending] = useState(false);
    const [receiver, setReceiver] = useState("");
    const [convertedReceiver, setConvertedReceiver] = useState(undefined);
    const [amount, setAmount] = useState("");

    const config = useConfig();
    const incomingFee = Number(evmNetwork?.incoming_fee ?? 0n) / 10000000;

    const {
        balance: ghstBalance,
        refetch: ghstBalanceRefetch
    } = useBalance(chainId, "GHST", address);

    const chainName = useMemo(() => {
        const client = config?.getClient();
        return client?.chain?.name;
    }, [config]);

    const chainNativeCurrency = useMemo(() => {
        const client = config?.getClient();
        return client?.chain?.nativeCurrency?.symbol;
    }, [config]);

    const chainExplorerUrl = useMemo(() => {
        const client = config?.getClient();
        return client?.chain?.blockExplorers?.default?.url;
    }, [config]);

    const preparedAmount = useMemo(() => {
        try {
            const result = BigInt(parseFloat(amount) *  Math.pow(10, 18));
            if (result > ghstBalance._value) {
                return ghstBalance._value;
            }
            return result;
        } catch {
            return 0n;
        }
    }, [amount]);

    const amountAfterFee = useMemo(() => {
        const convertedAmount = parseFloat(amount);
        if (!convertedAmount) {
            return 0;
        }
        return convertedAmount * (1 - incomingFee / 100);
    }, [amount, incomingFee]);

    const isDisabled = useMemo(() => {
        let isDisabled = isPending || gatekeeperAddressEmpty;
        if (address !== "") {
            isDisabled = isDisabled
                || !convertedReceiver
                || preparedAmount === 0n
                || ghstBalance._value < preparedAmount;
        }
        return isDisabled;
    }, [isPending, gatekeeperAddressEmpty, address, convertedReceiver, preparedAmount, ghstBalance]);

    const ghostFunds = async () => {
        setIsPending(true);
        try {
            const txHash = await ghost(chainId, address, convertedReceiver, preparedAmount);
            if (txHash) {
                storeTransactionHash(txHash, receiver, preparedAmount.toString());
            }
        } finally {
            await ghstBalanceRefetch();
            setReceiver("");
            setAmount("");
            setIsPending(false);
        }
    }

    useEffect(() => {
        if (isConfirmed) {
            setIsConfirmed(false);
            ghostFunds();
        }
    }, [isConfirmed]);

    const ghostOrConnect = async () => {
        if (address === "") {
            connect();
        } else if (!isConfirmed) {
            openBridgeModal();
        }
    }

    useEffect(() => {
        try {
            const [publicKey, prefix] = ss58Decode(receiver);
            if (prefix !== 1995 && prefix !== 1996) {
                throw new Error("bad prefix");
            }
            setConvertedReceiver(toHex(publicKey));
        } catch {
            setConvertedReceiver(undefined);
        }
    }, [receiver])

    return (
        <Box width="100%" height="340px" display="flex" flexDirection="column" justifyContent="space-between">
            <SwapCollection
                iconNotNeeded
                maxWidth="100%"
                UpperSwapCard={<SwapCard
                    id={`bridge-token-receiver`}
                    inputWidth={"100%"}
                    value={convertedReceiver ? sliceString(receiver, 15, -10) : receiver}
                    onChange={event => setReceiver(convertedReceiver ? "" : event.currentTarget.value)}
                    inputProps={{ "data-testid": "fromInput" }}
                    placeholder="GHOST address (sf prefixed)"
                    endString={convertedReceiver
                        ? <GhostStyledIcon color="success" viewBox="0 0 25 25" component={CheckCircleIcon} />
                        : undefined
                    }
                    type="text"
                    maxWidth="100%"
                />}
                LowerSwapCard={<SwapCard
                    id={`bridge-token-amount`}
                    inputWidth={"100%"}
                    info={`${formatCurrency(ghstBalance.toString(), 4, ghstSymbol)}`}
                    value={amount}
                    onChange={event => setAmount(event.currentTarget.value)}
                    inputProps={{ "data-testid": "fromInput" }}
                    endString={"Max"}
                    endStringOnClick={() => setAmount(ghstBalance.toString())}
                    maxWidth="100%"
                />}
            />
            <Box
                flexDirection="column"
                display="flex"
                gap="10px"
                justifyContent="space-between"
            >
                <Box width="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                    {gatekeeperAddressEmpty && (
                        <Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                            <Typography align="justify" mr="10px" variant="body2" color="textSecondary">
                                <em>
                                    There is no connected gatekeeper on {chainName} network yet.
                                </em>
                            </Typography>
                        </Box>
                    )}
                    {!gatekeeperAddressEmpty && (
                        <Box width="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                            {!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Gatekeeper:</Typography>}
                            <Link
                                fontSize="12px"
                                lineHeight="15px"
                                target="_blank"
                                rel="noopener noreferrer"
                                href={`${chainExplorerUrl}/token/${gatekeeperAddress}`}
                            >
                                {sliceString(gatekeeperAddress, 10, -8)}
                            </Link>
                        </Box>
                    )}
                </Box>
                <Box width="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                    <Box width="100%" display="flex" flexDirection="column" gap="0px">
                        <Box maxWidth="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                            {!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Bridge Fee:</Typography>}
                            {incomingFee
                                ? <Typography fontSize="12px" lineHeight="15px">{`${incomingFee.toFixed(4)}%`}</Typography>
                                : <Skeleton height={15} width="80px" />
                            }
                        </Box>
                        <Box maxWidth="100%" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                            {!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">You will get:</Typography>}
                            {incomingFee
                                ? <Typography fontSize="12px" lineHeight="15px">{amountAfterFee.toFixed(4)} {ghstSymbol}</Typography>
                                : <Skeleton height={15} width="80px" />
                            }
                        </Box>
                    </Box>
                </Box>
                <BridgeRoute coinName={ghstSymbol} chainTokenName={chainNativeCurrency} tokens={[ghstSymbol]} />
            </Box>
            <PrimaryButton
                fullWidth
                disabled={isDisabled}
                loading={isPending}
                onClick={() => ghostOrConnect()}
            >
                {address === "" ? "Connect" : isPending ? "Bridging..." : "Bridge" }
            </PrimaryButton>
        </Box>
    )
}

export const BridgeCardHistory = ({
    isSemiSmallScreen,
    isBigScreen,
    filteredStoredTransactions,
    ghstSymbol,
    blockNumber,
    finalityDelay,
    setActiveTxIndex
}) => {
    const isVeryBigScreen = useMediaQuery("(max-width: 1360px)");

    const theme = useTheme();
    const background = (index) => {
        return  index % 2 === 1 ? "" : theme.colors.gray[750];
    }

    return (
        <Box height="320px">
            <TableContainer
                component={Paper}
                className="custom-scrollbar"
                sx={{
                    height: "320px",
                    overflowY: 'scroll',
                    msOverflowStyle: "thin !important",
                    scrollbarWidth: "thin !important",
                }}
            >
                <Table sx={{ marginTop: "0px" }} stickyHeader aria-label="sticky available transactions">
                    <TableHead>
                        <TableRow sx={{ height: "40px" }}>
                            {!(isBigScreen ^ isVeryBigScreen) && <TableCell align="left" style={{ padding: "0px", paddingLeft: "16px", fontSize: "12px", borderTopLeftRadius: "3px", background: theme.colors.paper.cardHover }}>
                                Transaction
                            </TableCell>}
                            <TableCell align="center" style={{ padding: "0px", fontSize: "12px", background: theme.colors.paper.cardHover }}>
                                Datetime
                            </TableCell>
                            <TableCell align="center" style={{ padding: "0px", fontSize: "12px", borderTopRightRadius: "3px", background: theme.colors.paper.cardHover }}>
                                Status
                            </TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {filteredStoredTransactions?.map((obj, idx) => (
                            <TableRow
                                key={idx}
                                sx={{ cursor: "pointer", height: "30px" }}
                                id={idx + `--tx-history`}
                                data-testid={idx + `--tx-history`}
                                onClick={() => setActiveTxIndex(idx)}
                            >
                                {!(isBigScreen ^ isVeryBigScreen) && <TableCell style={{ background: background(idx) }}>
                                    <Box display="flex" flexDirection="column" justifyContent="center">
                                        <Typography variant="caption">
                                            {formatCurrency(
                                                new DecimalBigNumber(BigInt(obj.amount), 18).toString(),
                                                isSemiSmallScreen ? 3 : 8,
                                                ghstSymbol
                                            )}
                                        </Typography>
                                        <Typography variant="caption">
                                            {sliceString(
                                                obj.receiverAddress,
                                                isSemiSmallScreen ? 5 : 10,
                                                isSemiSmallScreen ? -3 : -8
                                            )}
                                        </Typography>
                                    </Box>
                                </TableCell>}

                                <TableCell style={{ background: background(idx) }}>
                                    <Box display="flex" flexDirection="column" alignItems="center" paddingLeft="5px">
                                        <Typography variant="caption">
                                            {new Date(obj.timestamp).toLocaleDateString('en-US')}
                                        </Typography>
                                        <Typography variant="caption">
                                            {new Date(obj.timestamp).toLocaleTimeString('en-US')}
                                        </Typography>
                                    </Box>
                                </TableCell>

                                <TableCell style={{ background: background(idx) }}>
                                    <Box display="flex" justifyContent="center" alignItems="center">
                                        <Box
                                            display="flex"
                                            justifyContent="center"
                                            alignItems="center"
                                            sx={{
                                                width: "20px",
                                                height: "20px",
                                                background: Number(blockNumber) - (obj.blockNumber + finalityDelay) < 0
                                                    ? theme.colors.feedback.warning
                                                    : theme.colors.feedback.success,
                                                borderRadius: "100%",
                                                boxShadow: "0px 0px 1px black"
                                            }}
                                        >
                                            {Number(blockNumber) - (obj.blockNumber + finalityDelay) < 0 ?
                                                <GhostStyledIcon
                                                    sx={{ width: "15px", height: "15px" }}
                                                    viewBox="0 0 25 25"
                                                    component={HourglassBottomIcon}
                                                />
                                                :
                                                <GhostStyledIcon
                                                    sx={{ width: "15px", height: "15px" }}
                                                    viewBox="0 0 25 25"
                                                    component={CheckIcon}
                                                />
                                            }
                                        </Box>
                                    </Box>
                                </TableCell>
                            </TableRow>
                        ))}
                    </TableBody>
                </Table>
            </TableContainer>
        </Box>
    )
}
