import {
    Box,
    Button,
    Container,
    Divider,
    HStack,
    Tab,
    TabList,
    TabPanel,
    TabPanels,
    Tabs,
    Text,
    useToast,
    VStack,
} from "@chakra-ui/react";
import React, { useState } from "react";
import { useAsync } from "react-async";
import { useEventSource } from "react-sse-hooks";
import { CfdTable } from "./components/cfdtables/CfdTable";
import { CfdTableMaker } from "./components/cfdtables/CfdTableMaker";
import CurrencyInputField from "./components/CurrencyInputField";
import useLatestEvent from "./components/Hooks";
import OrderTile from "./components/OrderTile";
import { Cfd, Order, WalletInfo } from "./components/Types";
import Wallet from "./components/Wallet";
import { CfdSellOrderPayload, postCfdSellOrderRequest } from "./MakerClient";

export default function App() {
    let source = useEventSource({ source: "/api/feed", options: { withCredentials: true } });

    const cfdsOrUndefined = useLatestEvent<Cfd[]>(source, "cfds");
    let cfds = cfdsOrUndefined ? cfdsOrUndefined! : [];
    const order = useLatestEvent<Order>(source, "order");

    console.log(cfds);

    const walletInfo = useLatestEvent<WalletInfo>(source, "wallet");

    const toast = useToast();
    let [minQuantity, setMinQuantity] = useState<string>("100");
    let [maxQuantity, setMaxQuantity] = useState<string>("1000");
    let [orderPrice, setOrderPrice] = useState<string>("10000");

    const format = (val: any) => `$` + val;
    const parse = (val: any) => val.replace(/^\$/, "");

    let { run: makeNewCfdSellOrder, isLoading: isCreatingNewCfdOrder } = useAsync({
        deferFn: async ([payload]: any[]) => {
            try {
                await postCfdSellOrderRequest(payload as CfdSellOrderPayload);
            } catch (e) {
                const description = typeof e === "string" ? e : JSON.stringify(e);

                toast({
                    title: "Error",
                    description,
                    status: "error",
                    duration: 9000,
                    isClosable: true,
                });
            }
        },
    });

    const runningStates = ["Accepted", "Contract Setup", "Pending Open"];
    const running = cfds.filter((value) => runningStates.includes(value.state));
    const openStates = ["Requested"];
    const open = cfds.filter((value) => openStates.includes(value.state));
    const closedStates = ["Rejected", "Closed"];
    const closed = cfds.filter((value) => closedStates.includes(value.state));
    // TODO: remove this. It just helps to detect immediately if we missed a state.
    const unsorted = cfds.filter((value) =>
        !runningStates.includes(value.state) && !closedStates.includes(value.state) && !openStates.includes(value.state)
    );

    const labelWidth = 110;

    return (
        <Container maxWidth="120ch" marginTop="1rem">
            <HStack spacing={5}>
                <VStack>
                    <Wallet walletInfo={walletInfo} />
                    <VStack spacing={5} shadow={"md"} padding={5} width="100%" align={"stretch"}>
                        <HStack>
                            <Text width={labelWidth} align={"left"}>Current Price:</Text>
                            <Text>{49000}</Text>
                        </HStack>
                        <HStack>
                            <Text width={labelWidth}>Min Quantity:</Text>
                            <CurrencyInputField
                                onChange={(valueString: string) => setMinQuantity(parse(valueString))}
                                value={format(minQuantity)}
                            />
                        </HStack>
                        <HStack>
                            <Text width={labelWidth}>Min Quantity:</Text>
                            <CurrencyInputField
                                onChange={(valueString: string) => setMaxQuantity(parse(valueString))}
                                value={format(maxQuantity)}
                            />
                        </HStack>
                        <HStack>
                            <Text width={labelWidth}>Order Price:</Text>
                            <CurrencyInputField
                                onChange={(valueString: string) => setOrderPrice(parse(valueString))}
                                value={format(orderPrice)}
                            />
                        </HStack>
                        <HStack>
                            <Text width={labelWidth}>Leverage:</Text>
                            <HStack spacing={5}>
                                <Button disabled={true}>x1</Button>
                                <Button disabled={true}>x2</Button>
                                <Button colorScheme="blue" variant="solid">x{5}</Button>
                            </HStack>
                        </HStack>
                        <Divider />
                        <Button
                            disabled={isCreatingNewCfdOrder}
                            variant={"solid"}
                            colorScheme={"blue"}
                            onClick={() => {
                                let payload: CfdSellOrderPayload = {
                                    price: Number.parseFloat(orderPrice),
                                    min_quantity: Number.parseFloat(minQuantity),
                                    max_quantity: Number.parseFloat(maxQuantity),
                                };
                                makeNewCfdSellOrder(payload);
                            }}
                        >
                            {order ? "Update Sell Order" : "Create Sell Order"}
                        </Button>
                    </VStack>
                </VStack>
                {order && <OrderTile order={order} />}
                <Box width="40%" />
            </HStack>

            <Tabs marginTop={5}>
                <TabList>
                    <Tab>Running [{running.length}]</Tab>
                    <Tab>Open [{open.length}]</Tab>
                    <Tab>Closed [{closed.length}]</Tab>
                    <Tab>Unsorted [{unsorted.length}] (should be empty)</Tab>
                </TabList>

                <TabPanels>
                    <TabPanel>
                        <CfdTable data={running} />
                    </TabPanel>
                    <TabPanel>
                        <CfdTableMaker data={open} />
                    </TabPanel>
                    <TabPanel>
                        <CfdTable data={closed} />
                    </TabPanel>
                    <TabPanel>
                        <CfdTable data={unsorted} />
                    </TabPanel>
                </TabPanels>
            </Tabs>
        </Container>
    );
}
