import { useRef, useMemo, useState, useEffect } from "react";
import { encodeFunctionData } from 'viem';
import { Box, Typography, TableRow, TableCell, useTheme } from "@mui/material";

import Modal from "../../../../components/Modal/Modal";
import Select from "../../../../components/Select/Select";
import { PrimaryButton, TertiaryButton } from "../../../../components/Button";
import { shorten } from "../../../../helpers";
import { useTokenSymbol } from "../../../../hooks/tokens";

import { ArgumentsWrapper, BooleanTrigger, ArgumentInput, ParsedCell } from "./index";

import {
    RESERVE_ADDRESSES,
    FTSO_DAI_LP_ADDRESSES,
    BOND_DEPOSITORY_ADDRESSES,
} from "../../../../constants/addresses";
import { abi as DepositoryAbi } from "../../../../abi/GhostBondDepository.json";

export const prepareCreateBondCalldata = (chainId, markets, terms, quoteToken, intervals, booleans) => {
    const value = 0n;
    const label = "create";
    const target = BOND_DEPOSITORY_ADDRESSES[chainId];
    const calldata = encodeFunctionData({
        abi: DepositoryAbi,
        functionName: 'create',
        args: [markets, terms, quoteToken, intervals, booleans]
    });
    return { label, target, calldata, value };
}

export const prepareCreateBondDescription = "function creates a new bond market by processing pricing, capacity, and term inputs. It initializes and stores the new bond market's complete configuration in the protocol.";

export const CreateBondParsed = (props) => {
    const [isOpened, setIsOpened] = useState(false);
    const { symbol: ftsoSymbol } = useTokenSymbol(props.chainId, "FTSO");
    console.log(props)
    return (
        <>
            <Modal
                headerContent={
                    <Box display="flex" justifyContent="center" alignItems="center" gap="15px">
                        <Typography variant="h4">View create</Typography>
                    </Box>
                }
                open={isOpened}
                onClose={() => setIsOpened(false)}
                maxWidth="460px"
                minHeight="200px"
            >
                <Box minHeight="220px" display="flex" alignItems="start" justifyContent="space-between" flexDirection="column">
                    <CreateBondSteps args={props.args} ftsoSymbol={ftsoSymbol} nativeCurrency={props.nativeCoin} {...props} />
                </Box>
            </Modal>
            <ParsedCell isOpened={isOpened} setIsOpened={setIsOpened} {...props} />
        </>
    )
}

export const CreateBondSteps = ({ nativeCurrency, ftsoSymbol, chainId, toInitialStep, addCalldata, args }) => {
    const createMode = args === undefined;

    const [step, setStep] = useState(1);
    const [nextDisabled, setNextDisabled] = useState(false);

    const [capacity, setCapacity] = useState(args?.at(0)?.at(0));
    const [initialPrice, setInitialPrice] = useState(args?.at(0)?.at(1));
    const [debtBuffer, setDebtBuffer] = useState(args?.at(0)?.at(2));

    const [depositInterval, setDepositInterval] = useState(args?.at(3)?.at(0));
    const [tuneInterval, setTuneInterval] = useState(args?.at(3)?.at(1));

    const [tokenAddress, setTokenAddress] = useState(args?.at(2));
    const [capacityInQuote, setCapacityInQuote] = useState(args?.at(4)?.at(0) ?? true);
    const [fixedTerm, setFixedTerm] = useState(args?.at(4)?.at(1) ?? false);

    const [vestingLength, setVestingLength] = useState(args?.at(1)?.at(0));
    const [conclusionTimestamp, setConclusionTimestamp] = useState(args?.at(1)?.at(1));

    const { symbol: reserveSymbol } = useTokenSymbol(chainId, RESERVE_ADDRESSES[chainId]);

    const handleProceed = () => {
        const markets = [capacity, initialPrice, debtBuffer];
        const terms = [vestingLength, conclusionTimestamp];
        const intervals = [depositInterval, tuneInterval];
        const booleans = [capacityInQuote, fixedTerm];

        addCalldata(prepareCreateBondCalldata(chainId, markets, terms, tokenAddress, intervals, booleans))
    }

    const empty = () => {};

    const incrementStep = () => {
        setStep(prev => prev + 1);
    }

    const decrementStep = () => {
        if (step > 1) setStep(prev => prev - 1);
        else toInitialStep();
    }

    const isNextDisabled = useMemo(() => {
        switch (step) {
            case 1:
                return tokenAddress === undefined;
            case 2:
                return !capacity || !initialPrice || !debtBuffer;
            case 3:
                return !depositInterval || !tuneInterval;
            case 4:
                return true;
            default:
                return false;
        }
    }, [step, tokenAddress, capacity, initialPrice, debtBuffer, depositInterval, tuneInterval]);

    const possibleTokens = [
        { value: FTSO_DAI_LP_ADDRESSES[chainId], symbol: `${ftsoSymbol}-${reserveSymbol} LP`, label: `${ftsoSymbol}-${reserveSymbol} LP: ${shorten(FTSO_DAI_LP_ADDRESSES[chainId])}` },
        { value: RESERVE_ADDRESSES[chainId], symbol: reserveSymbol, label: `${reserveSymbol}: ${shorten(RESERVE_ADDRESSES[chainId])}` },
    ];

    return (
        <Box height="100%" width="100%" display="flex" flexDirection="column" justifyContent="space-between">
            {step === 1 && <TokenAndBooleansArguments
                tokenAddress={tokenAddress}
                createMode={createMode}
                possibleTokens={possibleTokens}
                setTokenAddress={createMode ? setTokenAddress : empty}
                nativeCurrency={reserveSymbol}
                ftsoSymbol={ftsoSymbol}
                capacityInQuote={capacityInQuote}
                setCapacityInQuote={createMode ? setCapacityInQuote : empty}
                fixedTerm={fixedTerm}
                setFixedTerm={createMode ? setFixedTerm : empty}
            />}
            {step === 2 && <MarketArguments
                capacityInQuote={capacityInQuote}
                currencySymbol={possibleTokens.find(token => token.value === tokenAddress).symbol}
                ftsoSymbol={ftsoSymbol}
                capacity={capacity}
                setCapacity={createMode ? setCapacity : empty}
                initialPrice={initialPrice}
                setInitialPrice={createMode ? setInitialPrice : empty}
                debtBuffer={debtBuffer}
                setDebtBuffer={createMode ? setDebtBuffer : empty}
            />}
            {step === 3 && <IntervalsArguments
                depositInterval={depositInterval}
                setDepositInterval={createMode ? setDepositInterval : empty}
                tuneInterval={tuneInterval}
                setTuneInterval={createMode ? setTuneInterval : empty}
            />}
            {step === 4 && <TermsAgruments
                fixedTerm={fixedTerm}
                vestingLength={vestingLength}
                setVestingLength={createMode ? setVestingLength : empty}
                conclusionTimestamp={conclusionTimestamp}
                setConclusionTimestamp={createMode ? setConclusionTimestamp : empty}
            />}
            <Box width="100%" sx={{ marginTop: "20px" }} display="flex" flexDirection="column" gap="5px">
                <Box display="flex" gap="10px">
                    <TertiaryButton onClick={() => decrementStep()} fullWidth>Back</TertiaryButton>
                    <TertiaryButton disabled={isNextDisabled} onClick={() => incrementStep()} fullWidth>Next</TertiaryButton>
                </Box>
                {(step === 4 && createMode) && <PrimaryButton onClick={() => handleProceed()} fullWidth>Create Function</PrimaryButton>}
            </Box>
        </Box>
    );
}

const MarketArguments = ({
    capacityInQuote,
    currencySymbol,
    ftsoSymbol,
    capacity,
    setCapacity,
    initialPrice,
    setInitialPrice,
    debtBuffer,
    setDebtBuffer
}) => {
    return (
        <Box>
            <ArgumentInput
                endString={capacityInQuote ? currencySymbol : ftsoSymbol}
                label="market[0]"
                value={capacity ?? ""}
                setValue={setCapacity}
                tooltip={`Total capacity limit of the bond market denominated in ${capacityInQuote ? currencySymbol : ftsoSymbol}, representing the maximum amount of bonds that can be sold in this market.`}
            />
            <ArgumentInput
                endString={currencySymbol}
                label="market[1]"
                value={initialPrice ?? ""}
                setValue={setInitialPrice}
                tooltip={`Initial bond price of 1 ${ftsoSymbol} denominated in ${currencySymbol}. The bond price adjusts dynamically via Dutch auction based on market demand.`}
            />
            <ArgumentInput
                endString="%"
                label="market[2]"
                value={debtBuffer ?? ""}
                setValue={setDebtBuffer}
                tooltip="Debt buffer in basis points (e.g. 30,000 = 30%). Determines how far bond price can fall from initial price before tuning is triggered."
            />
        </Box>
    )
}

const IntervalsArguments = ({
    depositInterval,
    setDepositInterval,
    tuneInterval,
    setTuneInterval,
}) => {
    return (
        <Box>
            <ArgumentInput
                endString="seconds"
                label="_intervals[0]"
                value={depositInterval ?? ""}
                setValue={setDepositInterval}
                tooltip="Time in seconds that determines per-transaction bond purchase limit based on time until expiration. Higher values = larger per-transaction purchases allowed."
            />
            <ArgumentInput
                endString="seconds"
                label="_intervals[0]"
                value={tuneInterval ?? ""}
                setValue={setTuneInterval}
                tooltip="Time in seconds between bond price tuning events that evaluate actual vs. expected bond sales, adjusting how aggressively price decays in the next interval."
            />
        </Box>
    )
}

const TermsAgruments = ({
    fixedTerm,
    vestingLength,
    setVestingLength,
    conclusionTimestamp,
    setConclusionTimestamp,
}) => {
    return (
        <Box>
            <ArgumentInput
                endString="seconds"
                label={"_terms[0]"}
                value={vestingLength ?? ""}
                setValue={setVestingLength}
                tooltip={fixedTerm
                    ? "Time in seconds representing bond vesting schedule. Bond becomes fully claimable after this time elapses from purchase date."
                    : "Absolute Unix timestamp when all bonds mature and become fully claimable, regardless of the purchase date."
                }
            />
            <ArgumentInput
                endString="seconds"
                label="_terms[1]"
                value={conclusionTimestamp ?? ""}
                setValue={setConclusionTimestamp}
                tooltip="Unix timestamp when bond market stops accepting new purchases. Bond market closes after this time."
            />
        </Box>
    )
}

const TokenAndBooleansArguments = ({
    createMode,
    tokenAddress,
    possibleTokens,
    nativeCurrency,
    ftsoSymbol,
    setTokenAddress,
    capacityInQuote,
    setCapacityInQuote,
    fixedTerm,
    setFixedTerm,
}) => {
    const theme = useTheme();
    const [selectedOption, setSelectedOption] = useState(tokenAddress);

    const handleChange = (event) => {
        if (createMode) {
            setSelectedOption(event.target.value);
            setTokenAddress(event.target.value);
        }
    };

    return (
        <Box>
            <BooleanTrigger
                value={capacityInQuote}
                label="_booleans[0]"
                leftText={"True"}
                rightText={"False"}
                setLeftValue={() => setCapacityInQuote(true)}
                setRightValue={() => setCapacityInQuote(false)}
                tooltip={`Determines how the bond market capacity is measured. True = measured in _quoteToken, False = measured in ${ftsoSymbol}.`}
            />
            <BooleanTrigger
                value={fixedTerm}
                label="_booleans[1]"
                leftText="True"
                rightText="False"
                setLeftValue={() => setFixedTerm(true)}
                setRightValue={() => setFixedTerm(false)}
                tooltip={`Defines the bond maturity model. True = each purchase matures after vesting duration from its purchase date. False = all purchases mature at the conclusion timestamp.`}
            />
            <ArgumentsWrapper
                label="_quoteToken"
                tooltip={`ERC20 token that users pay with to purchase bonds (e.g. ${nativeCurrency} or ${nativeCurrency}-${ftsoSymbol} LP token).`}
            >
                <Select
                    value={selectedOption ?? ""}
                    onChange={handleChange}
                    options={possibleTokens}
                    inputWidth="100%"
                    renderValue={(selected) => {
                        if (!selected || selected.length === 0) {
                            return (
                                <span style={{ color: theme.colors.gray[500], opacity: 0.7 }}>
                                    Select payment token
                                </span>
                            );
                        }

                        return possibleTokens.find(opt => opt.value === selected)?.label || selected;
                    }}
                />
            </ArgumentsWrapper>
        </Box>
    )
}
