import { jsxs as _jsxs, jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
import { transformBalanceApiV2 as transformBalance } from "@equilab/utils/lib/transform/numbers";
import { capitalize } from "@equilab/utils/lib/format";
import BigNumber from "bignumber.js";
import React from "react";
import { usePagination, useTable, useSortBy, } from "react-table";
import { t } from "ttag";
import Button from "../button";
import Card from "../card";
import { Box, Section } from "../grid";
import Text from "../text";
import { useAssets } from "../../contexts/polkadot/assets";
import { safeToFixed } from "../../utils/format";
import { Table, THead, TBody, Row, Head, Item, Pagination } from "./styled";
import { useLink } from "../../hooks/locale";
import { Indicator } from "../indicator";
import Icons from "../icons";
var ReasonNum;
(function (ReasonNum) {
    ReasonNum[ReasonNum["InterestFee"] = 0] = "InterestFee";
    ReasonNum[ReasonNum["Transfer"] = 1] = "Transfer";
    ReasonNum[ReasonNum["Bailout"] = 2] = "Bailout";
    ReasonNum[ReasonNum["MarginCall"] = 3] = "MarginCall";
    ReasonNum[ReasonNum["Deposit"] = 4] = "Deposit";
    ReasonNum[ReasonNum["Withdraw"] = 5] = "Withdraw";
    ReasonNum[ReasonNum["Borrow"] = 6] = "Borrow";
    ReasonNum[ReasonNum["Repay"] = 7] = "Repay";
})(ReasonNum || (ReasonNum = {}));
const groupByBlockNumber = (data, ownAddress = []) => {
    const map = new Map();
    const defaultReason = 0;
    const collaterals = {};
    const debts = {};
    for (const entry of data) {
        const sign = entry.accountId1 && ownAddress.includes(entry.accountId1)
            ? new BigNumber(-1)
            : new BigNumber(1);
        let group;
        if (map.has(entry.blockNumber)) {
            group = map.get(entry.blockNumber);
        }
        else {
            group = {
                blockNumber: entry.blockNumber,
                reason: defaultReason,
                eqBuyout: {},
                amount: {},
                fee: undefined,
            };
        }
        if (!entry.currency1) {
            continue;
        }
        const currency = capitalize(entry.currency1);
        let nextReason;
        switch (entry.transferReason1) {
            case "MarginCall":
                nextReason = ReasonNum.MarginCall;
                break;
            case "InterestFee":
                nextReason = ReasonNum.InterestFee;
                break;
            case "BailsmenRedistribution":
                nextReason = ReasonNum.Bailout;
                break;
            case "Common":
            case "Subaccount":
                nextReason = ReasonNum.Transfer;
                break;
            default:
                nextReason = group.reason;
        }
        if (nextReason > group.reason) {
            group.reason = nextReason;
        }
        const prevCollateral = collaterals[currency];
        const prevDebt = debts[currency];
        if (entry.transferReason1 === "TreasuryEqBuyout") {
            if (!group.eqBuyout[currency]) {
                group.eqBuyout[currency] = sign.times(transformBalance(entry.balance1));
            }
            else {
                group.eqBuyout[currency] = group.eqBuyout[currency].plus(sign.times(transformBalance(entry.balance1)));
            }
        }
        else {
            if (!group.amount[currency]) {
                group.amount[currency] = sign.times(transformBalance(entry.balance1));
            }
            else {
                group.amount[currency] = group.amount[currency].plus(sign.times(transformBalance(entry.balance1)));
            }
        }
        if (group.amount[currency]?.lt(0)) {
            collaterals[currency] = (collaterals[currency] ?? new BigNumber(0, 10)).minus(group.amount[currency]?.abs() ?? 0);
            if (collaterals[currency]?.lt(0)) {
                const remCollat = collaterals[currency];
                collaterals[currency] = new BigNumber(0, 10);
                debts[currency] = (debts[currency] ?? new BigNumber(0, 10)).plus(remCollat?.abs() ?? 0);
            }
        }
        else {
            debts[currency] =
                entry.transferReason1 !== "InterestFee"
                    ? (debts[currency] ?? new BigNumber(0, 10)).minus(group.amount[currency]?.abs() ?? 0)
                    : debts[currency];
            if (debts[currency]?.lt(0)) {
                const remDebt = debts[currency];
                debts[currency] = new BigNumber(0, 10);
                collaterals[currency] = (collaterals[currency] ?? new BigNumber(0, 10)).plus(remDebt?.abs() ?? 0);
            }
        }
        const currCollateral = collaterals[currency];
        const currDebt = debts[currency];
        if (entry.transferReason1 === "Subaccount") {
            if (sign.eq(-1) && currDebt?.gt(prevDebt ?? 0)) {
                group.reason = ReasonNum.Borrow;
            }
            else if (sign.eq(1) &&
                currDebt?.lt(prevDebt ?? 0) &&
                // @ts-ignore
                currency !== "Gens") {
                group.reason = ReasonNum.Repay;
            }
            else if (sign.eq(-1)) {
                group.reason = ReasonNum.Withdraw;
            }
            else {
                group.reason = ReasonNum.Deposit;
            }
        }
        const collateralChange = currCollateral?.minus(prevCollateral ?? 0) ?? new BigNumber(0, 10);
        const debtChange = currDebt?.minus(prevDebt ?? 0) ?? new BigNumber(0, 10);
        const isTransfer = group.reason === ReasonNum.Transfer || group.reason >= ReasonNum.Deposit;
        if (collateralChange && !collateralChange.isZero()) {
            group.collateralChange = [currency, collateralChange];
        }
        if (debtChange && !debtChange.isZero()) {
            if (isTransfer) {
                group.debtChange = [currency, debtChange];
            }
            else if (!group.collateralChange) {
                group.collateralChange = [currency, debtChange.negated()];
            }
        }
        if (entry.extrinsic?.fee) {
            group.fee = new BigNumber(entry.extrinsic.fee, 10);
        }
        map.set(entry.blockNumber, group);
    }
    return Array.from(map).map(([, value]) => value);
};
const toDate = (block, { blockTime, firstBlockAt, }) => {
    if (blockTime && firstBlockAt) {
        return new Date(blockTime * block + firstBlockAt);
    }
};
export const HistoryTable = (props) => {
    const to = useLink();
    const ownAddress = React.useMemo(() => [props.bailsman, props.borrower], [props.bailsman, props.borrower]);
    const data = React.useMemo(() => groupByBlockNumber(props.data, ownAddress), [props.data, ownAddress]);
    const { native } = useAssets();
    const columns = React.useMemo(() => {
        const { blockTime, firstBlockAt } = props;
        const columns = [
            {
                id: "blockNumber",
                Header: (_jsx("div", { style: {
                        display: "flex",
                        flexFlow: "column",
                    }, children: _jsxs(Text.F2, { children: [firstBlockAt && _jsxs("span", { children: [t `Timestamp`, "/"] }), t `Block number`] }) })),
                accessor: "blockNumber",
                Cell: ({ value }) => (_jsx("div", { style: {
                        display: "flex",
                        flexFlow: "column",
                    }, children: firstBlockAt ? (_jsxs(_Fragment, { children: [_jsx(Text.T4, { children: toDate(value, { blockTime, firstBlockAt })?.toLocaleString() }), _jsx(Text.F1, { onClick: () => {
                                    to(`blockexplorer/block/${value}`);
                                }, style: { cursor: "pointer" }, gray: true, children: value })] })) : (_jsx(Text.T4, { children: value })) })),
            },
            {
                Header: _jsx(Text.F2, { children: t `Action` }),
                accessor: "reason",
                Cell: ({ value }) => {
                    let red = false;
                    let text = t `Interest fee`;
                    switch (value) {
                        case ReasonNum.Transfer:
                            text = t `Transfer`;
                            break;
                        case ReasonNum.MarginCall:
                            red = true;
                            text = t `Margin Call`;
                            break;
                        case ReasonNum.Bailout:
                            text = t `Bail out`;
                            break;
                        case ReasonNum.Deposit:
                            text = t `Deposit`;
                            break;
                        case ReasonNum.Withdraw:
                            text = t `Withdraw`;
                            break;
                        case ReasonNum.Borrow:
                            text = t `Borrow`;
                            break;
                        case ReasonNum.Repay:
                            text = t `Repay`;
                            break;
                        default:
                    }
                    return _jsx(Text.T4, { style: red ? { color: "red" } : {}, children: text });
                } /* TODO rename reason */,
            },
            {
                id: "amount",
                Header: _jsx(Text.F2, { textAlign: "right", children: t `Amount` }),
                accessor: (row) => {
                    return [row.amount, row.reason];
                },
                Cell: ({ value: rawValue, }) => {
                    const [value, reason] = rawValue;
                    const currs = Object.keys(value).filter((curr) => !!curr);
                    const positive = currs.filter((curr) => value?.[curr]?.isPositive());
                    const negative = currs.filter((curr) => !value?.[curr]?.isPositive());
                    const selected = [
                        ReasonNum.InterestFee,
                        ReasonNum.MarginCall,
                        ReasonNum.Borrow,
                        ReasonNum.Withdraw,
                    ].includes(reason)
                        ? negative
                        : positive;
                    const { token } = selected.reduce(({ max, token }, current) => {
                        if (max.lt(value?.[current]?.abs() ?? 0)) {
                            return { max: value?.[current]?.abs() ?? max, token: current };
                        }
                        return { max, token };
                    }, { max: new BigNumber(0), token: "-" });
                    const val = value?.[token] ?? new BigNumber(0);
                    return (_jsx(_Fragment, { children: _jsx("div", { style: {
                                display: "flex",
                                flexFlow: "column",
                                alignItems: "flex-end",
                            }, children: _jsxs(React.Fragment, { children: [_jsxs(Text.T4, { style: { color: val?.lte?.(0) ? "red" : "green" }, children: [safeToFixed(val, 4, true), "\u00A0", token.toUpperCase()] }), props.convert && (_jsxs(Text.F1, { gray: true, children: ["$", safeToFixed(props.convert(val?.abs(), token, "Usd"), 2, true)] }))] }, token.toString()) }) }));
                },
            },
            {
                id: "collateralChange",
                Header: _jsx(Text.F2, { textAlign: "right", children: t `Assets change` }),
                accessor: (row) => {
                    return [row.amount, row.reason];
                },
                Cell: ({ value: rawValue, }) => {
                    const [value, reason] = rawValue;
                    const currs = Object.keys(value).filter((curr) => !!curr);
                    const positive = currs.filter((curr) => value?.[curr]?.isPositive());
                    const negative = currs.filter((curr) => !value?.[curr]?.isPositive());
                    const selected = [ReasonNum.Deposit, ReasonNum.Bailout].includes(reason)
                        ? positive
                        : [
                            ReasonNum.Withdraw,
                            ReasonNum.MarginCall,
                            ReasonNum.InterestFee,
                        ].includes(reason)
                            ? negative
                            : undefined;
                    if (!selected) {
                        return null;
                    }
                    const { token } = selected.reduce(({ max, token }, current) => {
                        if (max.lt(value?.[current]?.abs() ?? 0)) {
                            return { max: value?.[current]?.abs() ?? max, token: current };
                        }
                        return { max, token };
                    }, { max: new BigNumber(0), token: "-" });
                    const val = value?.[token] ?? new BigNumber(0);
                    return (_jsx(_Fragment, { children: _jsx("div", { style: {
                                display: "flex",
                                flexFlow: "column",
                                alignItems: "flex-end",
                            }, children: _jsxs(React.Fragment, { children: [_jsxs(Text.T4, { style: { color: val?.lte?.(0) ? "red" : "green" }, children: [safeToFixed(val, 4, true), "\u00A0", token.toUpperCase()] }), props.convert && (_jsxs(Text.F1, { gray: true, children: ["$", safeToFixed(props.convert(val?.abs(), token, "Usd"), 2, true)] }))] }, token.toString()) }) }));
                },
            },
            {
                id: "debtChange",
                Header: _jsx(Text.F2, { textAlign: "right", children: t `Liabilities change` }),
                accessor: (row) => {
                    return [row.amount, row.reason];
                },
                Cell: ({ value: rawValue, }) => {
                    const [value, reason] = rawValue;
                    const currs = Object.keys(value).filter((curr) => !!curr);
                    const positive = currs.filter((curr) => value?.[curr]?.isPositive());
                    const negative = currs.filter((curr) => !value?.[curr]?.isPositive());
                    const selected = [ReasonNum.Borrow].includes(reason)
                        ? negative
                        : [ReasonNum.Repay].includes(reason)
                            ? positive
                            : undefined;
                    if (!selected) {
                        return null;
                    }
                    const { token } = selected.reduce(({ max, token }, current) => {
                        if (max.lt(value?.[current]?.abs() ?? 0)) {
                            return { max: value?.[current]?.abs() ?? max, token: current };
                        }
                        return { max, token };
                    }, { max: new BigNumber(0), token: "-" });
                    const val = value?.[token] ?? new BigNumber(0);
                    return (_jsx(_Fragment, { children: _jsx("div", { style: {
                                display: "flex",
                                flexFlow: "column",
                                alignItems: "flex-end",
                            }, children: _jsxs(React.Fragment, { children: [_jsxs(Text.T4, { style: { color: val?.lte?.(0) ? "red" : "green" }, children: [safeToFixed(val.times(-1), 4, true), "\u00A0", token.toUpperCase()] }), props.convert && (_jsxs(Text.F1, { gray: true, children: ["$", safeToFixed(props.convert(val?.abs(), token, "Usd"), 2, true)] }))] }, token.toString()) }) }));
                },
            },
            {
                id: "fee",
                Header: _jsx(Text.F2, { textAlign: "right", children: t `Fee` }),
                accessor: (row) => {
                    return [row.fee, row.reason];
                },
                // @ts-ignore
                Cell: ({ value }) => {
                    const [fee, reason] = value;
                    const hasFee = reason === ReasonNum.Transfer || reason >= ReasonNum.Deposit;
                    return (_jsx(_Fragment, { children: hasFee && fee ? (_jsxs("div", { style: {
                                display: "flex",
                                flexFlow: "column",
                                alignItems: "flex-end",
                            }, children: [_jsxs(Text.T4, { children: [safeToFixed(fee?.abs(), 4, true), "\u00A0", native.toUpperCase()] }), props.convert && (_jsxs(Text.F1, { gray: true, children: ["$", safeToFixed(props.convert(fee?.abs(), native, "Usd"), 2, true)] }))] })) : null }));
                },
            },
        ];
        return columns;
    }, [
        props.blockTime,
        props.firstBlockAt,
        props.bailsman,
        props.borrower,
        props.convert /* TODO lender */,
        native,
    ]);
    const table = useTable({
        columns,
        data,
        initialState: {
            // @ts-ignore
            pageIndex: 0,
        },
    }, useSortBy, usePagination);
    const { getTableProps, getTableBodyProps, headerGroups, prepareRow, 
    // pagination
    canPreviousPage, canNextPage, gotoPage, page, pageCount, previousPage, nextPage, setPageSize, 
    // @ts-ignore
    state: { pageIndex, pageSize }, } = table;
    const pagination = React.useMemo(() => (_jsx(Pagination, { children: _jsxs("div", { className: "container", children: [_jsx(Button
                // @ts-ignore
                , { 
                    // @ts-ignore
                    style: { background: "none", minWidth: 32 }, size: "xs", texted: true, disabled: !pageIndex, onClick: () => gotoPage(0), children: "<<" }), _jsx(Button
                // @ts-ignore
                , { 
                    // @ts-ignore
                    style: { background: "none", minWidth: 96 }, size: "xs", texted: true, disabled: !canPreviousPage, onClick: previousPage, children: t `< Prev` }), _jsx(Button
                // @ts-ignore
                , { 
                    // @ts-ignore
                    style: { background: "none", minWidth: 96 }, size: "xs", texted: true, disabled: !canNextPage, onClick: nextPage, children: t `Next >` }), _jsx(Button
                // @ts-ignore
                , { 
                    // @ts-ignore
                    style: { background: "none", minWidth: 32 }, texted: true, size: "xs", disabled: pageIndex >= pageCount - 1, onClick: () => gotoPage(pageCount - 1), children: ">>" }), _jsxs(Text.F1, { style: {
                        display: "flex",
                        alignItems: "center",
                        marginLeft: "auto",
                    }, children: [t `Page`, "\u00A0", pageIndex + 1, "\u00A0/\u00A0", pageCount] })] }) })), [pageIndex, pageCount, canNextPage, canPreviousPage]);
    return (_jsxs(Section, { children: [_jsx(Box, { mb: "16px", children: _jsx(Text.H2, { fontSize: 32, style: { textTransform: "uppercase" }, children: t `History` }) }), _jsxs(Card, { padding: "20px 24px 24px 24px", children: [pagination, _jsxs(Table, { cellSpacing: 0, ...getTableProps(), children: [_jsx(THead, { children: headerGroups.map((headerGroup) => (_jsx(Row, { ...headerGroup.getHeaderGroupProps(), children: headerGroup.headers.map((column) => (_jsxs(Head, { ...column.getHeaderProps(column.id === "blockNumber"
                                            ? // @ts-ignore
                                                column.getSortByToggleProps()
                                            : undefined), children: [column.render("Header"), column.id === "blockNumber" ? (_jsx(Indicator
                                            // @ts-ignore
                                            , { 
                                                // @ts-ignore
                                                opened: !column.isSorted || !column.isSortedDesc, width: "10", height: "10", viewBox: "0 0 10 9", fill: "none", xmlns: "http://www.w3.org/2000/svg", absolute: true, top: "calc(50% - 10px / 2)", right: "27px", children: _jsx(Icons.Arrow, {}) })) : null] }))) }))) }), _jsx(TBody, { ...getTableBodyProps(), children: page.map((row) => {
                                    prepareRow(row);
                                    return (_jsx(Row, { ...row.getRowProps(), children: row.cells.map((cell) => {
                                            return (_jsx(Item, { ...cell.getCellProps(), children: cell.render("Cell") }));
                                        }) }));
                                }) })] }), pagination] })] }));
};
//# sourceMappingURL=history.js.map