import { useState, useMemo } from "react";
import { useNavigate } from "react-router-dom";

import {
    Box,
    Link,
    Tabs,
    Tab,
    Table,
    TableBody,
    TableCell,
    TableContainer,
    TableHead,
    TableRow,
    Typography,
    useTheme,
    useMediaQuery
} from "@mui/material";
import { getBlockNumber } from "@wagmi/core";

import GhostStyledIcon from "../../../components/Icon/GhostIcon";
import ArrowUpIcon from "../../../assets/icons/arrow-up.svg?react";

import { networkAvgBlockSpeed } from "../../../constants";
import { prettifySecondsInDays, prettifySeconds } from "../../../helpers/timeUtil";

import Chip from "../../../components/Chip/Chip";
import Modal from "../../../components/Modal/Modal";
import Paper from "../../../components/Paper/Paper";
import LinearProgressBar from "../../../components/Progress/LinearProgressBar";
import { PrimaryButton, TertiaryButton } from "../../../components/Button";

import ProposalInfoText from "./ProposalInfoText";
import {
    convertStatusToTemplate,
    convertStatusToLabel,
    MY_PROPOSALS_PREFIX,
    VOTED_PROPOSALS_PREFIX
} from "../helpers";

import { useScreenSize } from "../../../hooks/useScreenSize";

import {
    useProposals,
} from "../../../hooks/governance";

const MAX_PROPOSALS_TO_SHOW = 10;

const ProposalsList = ({ chainId, address, config }) => {
    const isSmallScreen = useScreenSize("md");
    const navigate = useNavigate();
    const theme = useTheme();

    const [proposalsFilter, setProposalFilter] = useState("active");

    const myStoredProposals = localStorage.getItem(MY_PROPOSALS_PREFIX);
    const [myProposals, setMyProposals] = useState(
        myStoredProposals ? JSON.parse(myStoredProposals).map(id => BigInt(id)) : []
    );

    const storedVotedProposals = localStorage.getItem(VOTED_PROPOSALS_PREFIX);
    const [votedProposals, setVotedProposals] = useState(
        storedVotedProposals ? JSON.parse(storedVotedProposals).map(id => BigInt(id)) : []
    );

    const searchedIndexes = useMemo(() => {
        switch (proposalsFilter) {
            case "voted":
                return votedProposals;
            case "created":
                return myProposals;
            default:
                return undefined;
        }
    }, [proposalsFilter]);

    const [blockNumber, setBlockNumber] = useState(0n);
    const { proposals } = useProposals(chainId, MAX_PROPOSALS_TO_SHOW, searchedIndexes);

    getBlockNumber(config).then(block => setBlockNumber(block));

    if (proposals?.length === 0 && proposalsFilter === "active") {
        return (
            <Box display="flex" justifyContent="center">
                <Typography variant="h4">No proposals yet</Typography>
            </Box>
        );
    }

    if (isSmallScreen) {
        return (
            <Paper
                fullWidth
                enableBackground
                headerContent={
                    <Box display="flex" alignItems="center" flexDirection="row" gap="5px">
                        <Typography variant="h6">
                            Proposals
                        </Typography>
                    </Box>
                }
            >
                <Box display="flex" flexDirection="column" gap="40px">
                    {proposals?.map(proposal => (
                        <ProposalCard
                            key={proposal.hashes.short}
                            proposal={proposal}
                            blockNumber={blockNumber}
                            chainId={chainId}
                            openProposal={() => navigate(`/governance/${proposal.hashes.full}`)}
                        />
                    ))}
                </Box>

                {proposalsFilter === "active" && <Box my="24px" textAlign="center">
                    <ProposalInfoText />
                </Box>}
            </Paper>
        );
    }

    return (
        <Paper
            fullWidth
            enableBackground
            headerContent={
                <Box
                    width="100%"
                    display="flex"
                    alignItems="center"
                    justifyContent="space-between"
                    flexDirection="row"
                    gap="5px"
                >
                    <Typography variant="h6">
                        Proposals
                    </Typography>

                    <PrimaryButton
                        variant="text"
                        href="https://forum.ghostchain.io"
                    >
                        View Forum
                    </PrimaryButton>
                </Box>
            }
        >
            <ProposalFilterTrigger trigger={proposalsFilter} setTrigger={setProposalFilter} />

            <ProposalTable>
                {proposals?.map(proposal => (
                    <ProposalRow
                        key={proposal.hashes.short}
                        proposal={proposal}
                        blockNumber={blockNumber}
                        chainId={chainId}
                        openProposal={() => navigate(`/governance/${proposal.hashes.full}`)}
                    />
                ))}
            </ProposalTable>

            {proposalsFilter === "active" && <Box mt="24px" textAlign="center" width="70%" mx="auto">
                <ProposalInfoText />
            </Box>}
        </Paper>
    );
}

const ProposalTable = ({ children }) => (
    <TableContainer>
        <Table aria-label="Available bonds" style={{ tableLayout: "fixed" }}>
            <TableHead>
                <TableRow>
                    <TableCell align="center" style={{ width: "130px", padding: "8px 0" }}>Proposal ID</TableCell>
                    <TableCell align="center" style={{ width: "130px", padding: "8px 0" }}>Status</TableCell>
                    <TableCell align="center" style={{ padding: "8px 0" }}>Vote Ends</TableCell>
                    <TableCell align="center" style={{ padding: "8px 0" }}>Voting Stats</TableCell>
                    <TableCell align="center" style={{ padding: "8px 0" }}></TableCell>
                </TableRow>
            </TableHead>

            <TableBody>{children}</TableBody>
        </Table>
    </TableContainer>
);

const ProposalRow = ({ proposal, blockNumber, openProposal, chainId }) => {
    const theme = useTheme();

    const voteValue = useMemo(() => {
        const againstVotes = proposal?.votes?.at(0)?._value ?? 0n;
        const forVotes = proposal?.votes?.at(1)?._value ?? 0n;
        const totalVotes = againstVotes + forVotes;
        if (totalVotes == 0) {
            return 0;
        }
        return Number(forVotes * 100n / totalVotes);
    }, [proposal]);

    const voteTarget = useMemo(() => {
        const againstVotes = proposal?.votes?.at(0)?._value ?? 0n;
        const forVotes = proposal?.votes?.at(1)?._value ?? 0n;
        const totalVotes = againstVotes + forVotes;

        const first = (5n * againstVotes + forVotes);
        const second = BigInt(Math.floor(Math.sqrt(Number(totalVotes))));
        const bias = 3n * first + second;
        const denominator = totalVotes + bias;

        if (denominator === 0n) {
            return 80;
        }

        return Number(totalVotes * 100n / denominator);
    }, [proposal]);

    return (
        <TableRow id={proposal.hashes.short + `--proposal`} data-testid={proposal.hashes.short + `--proposal`}>
            <TableCell align="center" style={{ padding: "8px 0" }}>
                <Typography>GDP-{proposal.hashes.short}</Typography>
            </TableCell>

            <TableCell align="center" style={{ padding: "8px 0" }}>
                <Chip
                    sx={{ width: "100px" }}
                    label={convertStatusToLabel(proposal.state)}
                    template={convertStatusToTemplate(proposal.state)}
                />
            </TableCell>

            <TableCell align="center" style={{ padding: "8px 0" }}>
                <Typography>
                    {convertDeadline(
                        proposal.deadline,
                        blockNumber,
                        chainId
                    )}
                </Typography>
            </TableCell>

            <TableCell align="center" style={{ padding: "8px 0" }}>
                <Box marginLeft="15px" marginRight="15px">
                    <LinearProgressBar
                        barColor={theme.colors.feedback.success}
                        barBackground={theme.colors.feedback.error}
                        variant="determinate"
                        value={voteValue}
                        target={voteTarget}
                    />
                </Box>
            </TableCell>

            <TableCell align="center" style={{ padding: "8px 0" }}>
                {(proposal.state === "Active" || proposal.state === "Succeeded") && <PrimaryButton
                    fullWidth
                    onClick={() => openProposal()}
                    sx={{ maxWidth: "130px" }}
                >
                    {proposal.state === "Succeeded" ? "Execute" : "Vote"}
                </PrimaryButton>}
                {(proposal.state !== "Active" && proposal.state !== "Succeeded") && <TertiaryButton
                    fullWidth
                    onClick={() => openProposal()}
                    sx={{ alignSelf: "right", maxWidth: "130px" }}
                >
                    View
                </TertiaryButton>}
            </TableCell>
        </TableRow>
    );
}

const ProposalCard = ({ proposal, blockNumber, openProposal, chainId }) => {
    const theme = useTheme();
    const isSmallScreen = useMediaQuery('(max-width: 450px)');

    return (
        <Box id={proposal.hashes.short + `--proposal`} data-testid={proposal.hashes.short + `--proposal`}>
            <Box display="flex" flexDirection={isSmallScreen ? "column" : "row"} justifyContent="space-between">
                <Box display="flex" flexDirection="column" width="100%">
                    <Box display="flex" flexDirection="row" alignItems="center" width="100%" gap="10px">
                        <Typography variant="h3">GIP-{proposal.hashes.short}</Typography>
                        <Chip
                            sx={{ width: "88px" }}
                            label={convertStatusToLabel(proposal.state)}
                            template={convertStatusToTemplate(proposal.state)}
                        />
                    </Box>
                    <Typography>
                        {convertDeadline(
                            proposal.deadline,
                            blockNumber,
                            chainId
                        )}
                    </Typography>
                </Box>
            </Box>

            <Box marginTop="15px" marginBottom="15px">
                <LinearProgressBar
                    barColor={theme.colors.feedback.success}
                    barBackground={theme.colors.feedback.error}
                    variant="determinate"
                    value={69}
                    target={Math.floor(Math.random() * 101)}
                />
            </Box>
            <Box marginBottom="20px">
                {(proposal.state === "Active" || proposal.state === "Succeeded") && <PrimaryButton
                    fullWidth
                    onClick={() => openProposal()}
                >
                    {proposal.state === "Succeeded" ? "Execute" : "Vote"}
                </PrimaryButton>}
                {(proposal.state !== "Active" && proposal.state !== "Succeeded") && <TertiaryButton
                    fullWidth
                    onClick={() => openProposal()}
                >
                    View
                </TertiaryButton>}
            </Box>
        </Box>
    );
};

const ProposalFilterTrigger = ({ trigger, setTrigger }) => {
    return (
        <Tabs
            centered
            textColor="primary"
            indicatorColor="primary"
            value={trigger}
            aria-label="Proposal filter tabs"
            onChange={(_, view) => setTrigger(view)}
            TabIndicatorProps={{ style: { display: "none" } }}
        >
            <Tab aria-label="proposal-filter-active-button" value="active" label="Active" style={{ fontSize: "1rem" }} />
            <Tab aria-label="proposal-filter-voted-button" value="voted" label="Voted" style={{ fontSize: "1rem" }} />
            <Tab aria-label="proposal-filter-created-button" value="created" label="Created" style={{ fontSize: "1rem" }} />
        </Tabs>
    )
}

const convertDeadline = (deadline, blockNumber, chainId) => {
    const diff = blockNumber > deadline ? blockNumber - deadline : deadline - blockNumber;
    const voteSeconds = Number(diff * networkAvgBlockSpeed(chainId));

    const result = prettifySeconds(voteSeconds, "mins");
    if (result === "now") {
        return new Date(Date.now()).toLocaleDateString('en-US', {
            year: 'numeric',
            month: 'short',
            day: 'numeric'
        });
    }

    return `in ${result}`;
}

export default ProposalsList;
