import { useEffect, useState, useMemo, useCallback } from "react";

import {
    Box,
    Container,
    Typography,
    Link,
    Table,
    TableBody,
    TableCell,
    TableHead,
    TableRow,
    TableContainer,
    useMediaQuery,
    useTheme
} from "@mui/material";
import { ss58Decode } from "@polkadot-labs/hdkd-helpers";
import { toHex } from "@polkadot-api/utils";
import { useBlockNumber, useTransactionConfirmations } from "wagmi";

import PendingActionsIcon from '@mui/icons-material/PendingActions';
import PublicIcon from '@mui/icons-material/Public';
import ArrowRightIcon from '@mui/icons-material/ArrowRight';
import HourglassBottomIcon from '@mui/icons-material/HourglassBottom';
import ThumbUpIcon from '@mui/icons-material/ThumbUp';
import ThumbDownAltIcon from '@mui/icons-material/ThumbDownAlt';
import CheckCircleIcon from '@mui/icons-material/CheckCircle';
import CheckIcon from '@mui/icons-material/Check';

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

import { GATEKEEPER_ADDRESSES } from "../../constants/addresses";
import { DecimalBigNumber } from "../../helpers/DecimalBigNumber";
import { formatCurrency } from "../../helpers";

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

const STORAGE_PREFIX = "storedTransactions"

const Bridge = ({ chainId, address, config, connect }) => {
    const theme = useTheme();
    const isSmallScreen = useMediaQuery("(max-width: 650px)");
    const isSemiSmallScreen = useMediaQuery("(max-width: 480px)");
    const isVerySmallScreen = useMediaQuery("(max-width: 379px)");

    const [isPending, setIsPending] = useState(false);
    const [bridgeAction, setBridgeAction] = useState(true);
    const [activeTxIndex, setActiveTxIndex] = useState(-1);
    const [txStep, setTxStep] = useState(0);
    const [receiver, setReceiver] = useState("");
    const [convertedReceiver, setConvertedReceiver] = useState(undefined);
    const [amount, setAmount] = useState("");

    // ReceivedClaps && ApplausesForTransaction
    // session_index
    // transaction_hash
    // keccak256(receiver, amount, chain_id)

    // const initialStoredTransactions = sessionStorage.getItem(STORAGE_PREFIX);
    const initialStoredTransactions = JSON.stringify([
        {
            sessionIndex: 23,
            transactionHash: "0x11111111111111111",
            receiver: "sfAasdadasasads",
            amount: "2312323232223232",
            chainId: 11155111,
            timestamp: Date.now()
        },
        {
            sessionIndex: 23,
            transactionHash: "0x2222222222222222222",
            receiver: "sfAasdadasasads",
            amount: "1122232232",
            chainId: 1,
            timestamp: Date.now()
        },
        {
            sessionIndex: 24,
            transactionHash: "0x333333333333333333",
            receiver: "sfAasdadasasads",
            amount: "99999999999999992",
            chainId: 11155111,
            timestamp: Date.now()
        },
        {
            sessionIndex: 23,
            transactionHash: "0x4444444444444444444",
            receiver: "sfAasdadasasads",
            amount: "2312323232223232",
            chainId: 11155111,
            timestamp: Date.now()
        },
        {
            sessionIndex: 23,
            transactionHash: "0x555555555555555555555",
            receiver: "sfAasdadasasads",
            amount: "1122232232",
            chainId: 1,
            timestamp: Date.now()
        },
        {
            sessionIndex: 24,
            transactionHash: "0x66666666666666666666666666",
            receiver: "sfAasdadasasads",
            amount: "99999999999999992",
            chainId: 11155111,
            timestamp: Date.now()
        },
        {
            sessionIndex: 23,
            transactionHash: "0x77777777777777777777777777",
            receiver: "sfAasdadasasads",
            amount: "2312323232223232",
            chainId: 11155111,
            timestamp: Date.now()
        },
        {
            sessionIndex: 23,
            transactionHash: "0x888888888888888888888888888",
            receiver: "sfAasdadasasads",
            amount: "1122232232",
            chainId: 1,
            timestamp: Date.now()
        },
        {
            sessionIndex: 24,
            transactionHash: "0x999999999999999999999",
            receiver: "sfAasdadasasads",
            amount: "99999999999999992",
            chainId: 11155111,
            timestamp: Date.now()
        },
        {
            sessionIndex: 23,
            transactionHash: "0x10101010101010101010",
            receiver: "sfAasdadasasads",
            amount: "2312323232223232",
            chainId: 11155111,
            timestamp: Date.now()
        },
        {
            sessionIndex: 23,
            transactionHash: "0x12121212121212212",
            receiver: "sfAasdadasasads",
            amount: "1122232232",
            chainId: 1,
            timestamp: Date.now()
        },
        {
            sessionIndex: 24,
            transactionHash: "0x1313131313131313131",
            receiver: "sfAasdadasasads",
            amount: "99999999999999992",
            chainId: 11155111,
            timestamp: Date.now()
        }
    ]);
    const [storedTransactions, setStoredTransactions] = useState(
        initialStoredTransactions ? JSON.parse(initialStoredTransactions) : []
    );

    const incomingCommission = new DecimalBigNumber(69n, 100);
    const validators = ["first", "second", "third"];
    const clappedValidators = 1;

    const { data: blockNumber } = useBlockNumber({ watch: true });
    // const { data: txtx } = useTransactionConfirmations({
    //     hash: "0xdb30adfa3bfc58539bc3a9a92f0dcace8f251af90f8a4f525b57d95d28103afc",
    //     refetchInterval: 5000
    // });
    // console.log(txtx)
    const { gatekeeperAddress } = useGatekeeperAddress(chainId);
    const { symbol: ghstSymbol } = useTokenSymbol(chainId, "GHST");
    const {
        balance: ghstBalance,
        refetch: ghstBalanceRefetch
    } = useBalance(chainId, "GHST", address);

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

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

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

    const currentRecord = useMemo(() => {
        if (activeTxIndex === -1) return undefined
        return storedTransactions.at(activeTxIndex)
    }, [activeTxIndex, storedTransactions]);

    const gatekeeperAddressEmpty = useMemo(() => {
        if (gatekeeperAddress === "0x0000000000000000000000000000000000000000") {
            return true;
        }
        return false;
    }, [gatekeeperAddress]);

    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 filteredStoredTransactions = useMemo(() => {
        return storedTransactions.filter(obj => obj.chainId === chainId);
    }, [storedTransactions, chainId]);

    const removeStoredRecord = useCallback(() => {
        const newStoredTransactions = storedTransactions.filter((_, index) => index !== activeTxIndex)
        setStoredTransactions(newStoredTransactions);
        sessionStorage.setItem(STORAGE_PREFIX, JSON.stringify(newStoredTransactions));
        setActiveTxIndex(-1);
    }, [storedTransactions, activeTxIndex, setStoredTransactions, setActiveTxIndex]);

    const handleMouseEnter = (index) => {
        setTxStep(index);
    }

    const ghostOrConnect = async () => {
        if (address === "") {
            connect();
        } else {
            setIsPending(true);

            const txHash = await ghost(chainId, address, convertedReceiver, preparedAmount);
            await ghstBalanceRefetch();

            setReceiver("");
            setAmount("");
            setIsPending(false);
        }
    }

    return (
        <Box height="calc(100vh - 43px)">
            <PageTitle name="GHOST Bridge" subtitle="The only pure Web3 decentralized bridge." />
            <Container
                style={{
                    paddingLeft: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
                    paddingRight: isSmallScreen || isVerySmallScreen ? "0" : "3.3rem",
                    display: "flex",
                    justifyContent: "center",
                    alignItems: "center",
                    height: "calc(100vh - 153px)"
                }}
            >
                <Modal
                    data-testid="transaction-details-modal"
                    maxWidth="476px"
                    headerContent={
                        <Box display="flex" flexDirection="row">
                            <Typography variant="h5">
                                TX Hash&nbsp;
                                <Link
                                    sx={{
                                        margin: "0px",
                                        font: "inherit",
                                        letterSpacing: "inherit",
                                        textDecoration: "underline",
                                        color: theme.colors.gray[10],
                                        textUnderlineOffset: "0.23rem",
                                        cursor: "pointer",
                                        textDecorationThickness: "3px",
                                        "&:hover": {
                                            textDecoration: "underline",
                                        }
                                    }}
                                    target="_blank"
                                    rel="noopener noreferrer"
                                    href={currentRecord
                                        ? `${chainExplorerUrl}/tx/${currentRecord.transactionHash}`
                                        : ""
                                    }
                                >
                                    {currentRecord?.transactionHash.slice(0, 9)}...{currentRecord?.transactionHash.slice(-9)}
                                </Link>
                            </Typography>
                        </Box>
                    }
                    open={activeTxIndex > -1}
                    onClose={() => setActiveTxIndex(-1)}
                    minHeight={"100px"}
                >
                    <Box display="flex" gap="1.5rem" flexDirection="column" marginTop=".8rem">
                        <Box display="flex" flexDirection="row" justifyContent="space-between" alignItems="center">
                            <Box
                                sx={{
                                    transition: "all 0.2s ease",
                                    transform: txStep === 0 && "scale(1.1)",
                                    color: txStep === 0 && theme.colors.primary[300]
                                }}
                                width="120px"
                                display="flex"
                                flexDirection="column"
                                justifyContent="start"
                                alignItems="center"
                                onMouseEnter={() => handleMouseEnter(0)}
                            >
                                <GhostStyledIcon
                                    sx={{ width: "35px", height: "35px" }}
                                    viewBox="0 0 25 25"
                                    component={HourglassBottomIcon}
                                />
                                <Typography variant="caption">Finalization</Typography>
                                <Typography variant="caption">{blockNumber?.toString()} blocks left</Typography>
                            </Box>

                            <GhostStyledIcon
                                sx={{ transition: "all 0.2s ease", opacity: txStep < 1 && "0.2" }}
                                component={ArrowRightIcon}
                            />

                            <Box
                                sx={{
                                    transition: "all 0.2s ease",
                                    opacity: txStep < 1 && "0.2",
                                    transform: txStep === 1 && "scale(1.1)",
                                    color: txStep === 1 && theme.colors.primary[300]
                                }}
                                width="120px"
                                display="flex"
                                flexDirection="column"
                                justifyContent="start"
                                alignItems="center"
                                onMouseEnter={() => handleMouseEnter(1)}
                            >
                                <Box display="flex" flexDirection="row" justifyContent="center" alignItems="center">
                                    <GhostStyledIcon
                                        sx={{ width: "35px", height: "35px" }}
                                        viewBox="0 0 25 25"
                                        component={ThumbUpIcon}
                                    />
                                    <GhostStyledIcon
                                        sx={{ width: "35px", height: "35px" }}
                                        viewBox="0 0 25 25"
                                        component={ThumbDownAltIcon}
                                    />
                                </Box>
                                <Box display="flex" flexDirection="column" justifyContent="center" alignItems="center">
                                    <Typography variant="caption">Slow claps</Typography>
                                    <Typography variant="caption">{clappedValidators} / {validators.length}</Typography>
                                </Box>
                            </Box>

                            <GhostStyledIcon
                                sx={{ transition: "all 0.2s ease", opacity: txStep < 2 && "0.2" }}
                                component={ArrowRightIcon}
                            />

                            <Box
                                sx={{
                                    transition: "all 0.2s ease",
                                    opacity: txStep < 2 && "0.2",
                                    transform: txStep === 2 && "scale(1.1)",
                                    color: txStep === 2 && theme.colors.primary[300]
                                }}
                                width="120px"
                                display="flex"
                                flexDirection="column"
                                justifyContent="start"
                                alignItems="center"
                                onMouseEnter={() => handleMouseEnter(2)}
                            >
                                <GhostStyledIcon
                                    sx={{ width: "35px", height: "35px" }}
                                    viewBox="0 0 25 25"
                                    component={CheckCircleIcon}
                                />
                                <Typography variant="caption">Applaused</Typography>
                                <Typography variant="caption">Check Receiver</Typography>
                            </Box>
                        </Box>

                        <Box display="flex" flexDirection="column" gap="5px" padding="0.6rem 0">
                            <Box display="flex" flexDirection="row" justifyContent="space-between">
                                <Typography variant="body2">Session Index:</Typography>
                                <Typography variant="body2">{currentRecord?.sessionIndex}</Typography>
                            </Box>
                            <Box display="flex" flexDirection="row" justifyContent="space-between">
                                <Typography variant="body2">Receiver Address:</Typography>
                                <Typography variant="body2">{currentRecord?.receiver}</Typography>
                            </Box>
                            <Box display="flex" flexDirection="row" justifyContent="space-between">
                                <Typography variant="body2">Sent Amount:</Typography>
                                <Typography variant="body2">{formatCurrency(
                                    new DecimalBigNumber(
                                        BigInt(currentRecord ? currentRecord.amount : "0"),
                                        18
                                    ).toString(), 9, ghstSymbol)
                                }</Typography>
                            </Box>
                            <Box display="flex" flexDirection="row" justifyContent="space-between">
                                <Typography variant="body2">Executed at:</Typography>
                                <Typography variant="body2">{
                                    new Date(currentRecord ? currentRecord.timestamp : 0).toLocaleString('en-US')
                                }</Typography>
                            </Box>
                        </Box>


                        <Box display="flex" flexDirection="column" gap="5px">
                            <PrimaryButton
                                fullWidth
                                disabled={address === ""}
                                loading={false}
                                onClick={() => removeStoredRecord()}
                            >
                                Erase Record
                            </PrimaryButton>

                            <Typography variant="body2" sx={{ fontStyle: "italic" }}>
                                This will remove the transaction record from the session storage, but it will not cancel the bridge transaction.
                            </Typography>
                        </Box>
                    </Box>
                </Modal>
                <Box width="100%" maxWidth="476px" display="flex" alignItems="center" justifyContent="center" flexDirection="column">
                    <Paper
                        headerContent={
                            <Box alignItems="center" justifyContent="space-between" display="flex" width="100%">
                                <Typography variant="h4">{
                                    bridgeAction
                                        ? `Bridge $${ghstSymbol}`
                                        : "Transaction history"
                                }</Typography>
                            </Box>
                        }
                        topRight={
                            <GhostStyledIcon
                                component={bridgeAction ? PendingActionsIcon : PublicIcon}
                                viewBox="0 0 23 23"
                                style={{ display: "flex", alignItems: "center", cursor: "pointer" }}
                                onClick={() => setBridgeAction(!bridgeAction)}
                            />
                        }

                        enableBackground
                        fullWidth
                    >
                        <Box minHeight="300px" display="flex" flexDirection="column" gap="5px">
                            {bridgeAction && (
                                <>
                                    <SwapCollection
                                        iconNotNeeded
                                        UpperSwapCard={<SwapCard
                                            id={`bridge-token-receiver`}
                                            inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
                                            value={receiver}
                                            onChange={event => setReceiver(event.currentTarget.value)}
                                            inputProps={{ "data-testid": "fromInput" }}
                                            placeholder="Ghost address (sf prefixed)"
                                            type="text"
                                        />}
                                        LowerSwapCard={<SwapCard
                                            id={`bridge-token-amount`}
                                            inputWidth={isVerySmallScreen ? "100px" : isSemiSmallScreen ? "180px" : "250px"}
                                            info={`${formatCurrency(ghstBalance.toString(), 4, ghstSymbol)}`}
                                            value={amount}
                                            onChange={event => setAmount(event.currentTarget.value)}
                                            inputProps={{ "data-testid": "fromInput" }}
                                            endString={"Max"}
                                            endStringOnClick={() => setAmount(ghstBalance.toString())}
                                        />}
                                    />
                                    <Box
                                        mb="20px"
                                        mt="20px"
                                        flexDirection="column"
                                        display="flex"
                                        gap="10px"
                                        justifyContent="space-between"
                                    >
                                        <Box display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                                            {gatekeeperAddressEmpty && (
                                                <Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                                                    <Typography mr="10px" variant="body2" color="textSecondary">
                                                        <em>
                                                            There is no connected gatekeeper on {chainName} network. Propose gatekeeper on this network to make validators listen to it.
                                                        </em>
                                                    </Typography>
                                                </Box>
                                            )}
                                            {!gatekeeperAddressEmpty && (
                                                <>
                                                    {!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Gatekeeper:</Typography>}
                                                    <Link
                                                        fontSize="12px"
                                                        lineHeight="15px"
                                                        target="_blank"
                                                        rel="noopener noreferrer"
                                                        href={`${chainExplorerUrl}/token/${gatekeeperAddress}`}
                                                    >
                                                        {gatekeeperAddress.slice(0, 10) + "..." + gatekeeperAddress.slice(-8)}
                                                    </Link>
                                                </>
                                            )}
                                        </Box>
                                        {incomingCommission && validators?.length ? (
                                            <Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                                                <Typography mr="10px" variant="body2" color="textSecondary">
                                                    <em>
                                                        GHOST Wallet is not detected on your browser. Download&nbsp;
                                                        <Link
                                                            target="_blank"
                                                            rel="noopener noreferrer"
                                                            href="https://git.ghostchain.io/ghostchain/ghost-extension-wallet/releases"
                                                        >
                                                            GHOST Wallet
                                                        </Link>&nbsp; to see full detalization for bridge transaction.
                                                    </em>
                                                </Typography>
                                            </Box>
                                        )
                                        : (
                                            <Box display="flex" flexDirection="column" gap="0px">
                                                <Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                                                    {!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Est. Commission:</Typography>}
                                                    <Typography fontSize="12px" lineHeight="15px">unknown</Typography>
                                                </Box>
                                                <Box maxWidth="416px" display="flex" justifyContent={isVerySmallScreen ? "end" : "space-between"}>
                                                    {!isVerySmallScreen && <Typography fontSize="12px" lineHeight="15px">Number of validators:</Typography>}
                                                    <Typography fontSize="12px" lineHeight="15px">unknown</Typography>
                                                </Box>
                                            </Box>
                                        )}

                                    </Box>
                                    <PrimaryButton
                                        fullWidth
                                        disabled={
                                            address === "" || gatekeeperAddressEmpty || !convertedReceiver ||
                                            preparedAmount === 0n || ghstBalance._value < preparedAmount
                                        }
                                        loading={isPending}
                                        onClick={() => ghostOrConnect()}
                                    >
                                        {address === "" ?
                                            "Connect"
                                            :
                                            "Bridge"
                                        }
                                    </PrimaryButton>
                                </>
                            )}
                            {!bridgeAction && (
                                <Box>
                                    <Box display="grid" gridTemplateColumns="1fr 1fr 60px" sx={{ padding: "0.6rem", borderBottom: "1px solid" }}>
                                        <Typography variant="subtitle1" sx={{ fontWeight: "bold" }}>Amount</Typography>
                                        <Typography variant="subtitle1" sx={{ fontWeight: "bold" }}>Datetime</Typography>
                                        <Typography variant="subtitle1" sx={{ justifySelf: "center", fontWeight: "bold" }}>Status</Typography>
                                    </Box>
                                    <Box display="flex" flexDirection="column" sx={{
                                        height: "250px",
                                        overflowY: "scroll",
                                        "-ms-overflow-style": "thin !important",
                                        "scrollbar-width": "thin !important",
                                    }}>
                                        {filteredStoredTransactions
                                            .map((obj, idx) => (
                                                <Box
                                                    display="grid"
                                                    gridTemplateColumns="1fr 1fr 60px"
                                                    sx={{
                                                        borderBottom: "1px solid",
                                                        padding: "0.6rem",
                                                        paddingTop: "1.2rem",
                                                        cursor: 'pointer',
                                                        '&:hover': {
                                                            background: theme.colors.paper.cardHover
                                                        }
                                                    }}
                                                    key={obj.transactionHash}
                                                    onClick={() => setActiveTxIndex(idx)}
                                                >
                                                    <Box display="flex" flexDirection="column" justifyContent="center">
                                                        <Typography variant="subtitle2">
                                                            {formatCurrency(
                                                                new DecimalBigNumber(BigInt(obj.amount), 18).toString(),
                                                                3,
                                                                ghstSymbol
                                                            )}
                                                        </Typography>
                                                    </Box>

                                                    <Box display="flex" flexDirection="column">
                                                        <Typography variant="subtitle2">
                                                            {new Date(obj.timestamp).toLocaleDateString('en-US')}
                                                        </Typography>
                                                        <Typography variant="subtitle2">
                                                            {new Date(obj.timestamp).toLocaleTimeString('en-US')}
                                                        </Typography>
                                                    </Box>

                                                    <Box display="flex" justifyContent="center" alignItems="center">
                                                        <Box
                                                            display="flex"
                                                            justifyContent="center"
                                                            alignItems="center"
                                                            sx={{
                                                                width: "25px",
                                                                height: "25px",
                                                                background: idx % 2 === 0
                                                                    ? theme.colors.feedback.warning
                                                                    : theme.colors.feedback.success,
                                                                borderRadius: "100%",
                                                                boxShadow: "0px 0px 1px black"
                                                            }}
                                                        >
                                                            {idx % 2 === 0 ?
                                                                <GhostStyledIcon
                                                                    sx={{ width: "20px", height: "20px" }}
                                                                    viewBox="0 0 25 25"
                                                                    component={HourglassBottomIcon}
                                                                />
                                                                :
                                                                <GhostStyledIcon
                                                                    sx={{ width: "20px", height: "20px" }}
                                                                    viewBox="0 0 25 25"
                                                                    component={CheckIcon}
                                                                />
                                                            }
                                                        </Box>
                                                    </Box>
                                                </Box>
                                        ))}
                                    </Box>
                                </Box>
                            )}
                        </Box>
                    </Paper>
                </Box>
            </Container>
        </Box>
    )
}

export default Bridge;
