import React, {useCallback, useEffect, useState} from 'react'
import PropTypes from 'prop-types'
import ric from 'request-idle-callback'
import orderStatuses from 'common-fe/constants/order-statuses'
import requestStatuses from 'common-fe/constants/request-statuses'
import rankingPeriods from 'global/constants/ranking-periods'
import {Provider, withPublicPortfolio} from './context'

import {Flex} from 'react-uikit/layout'
import TabsWithSlider from 'react-uikit/tabs/with-slider'
import modalTypes from 'containers/modal-manager/modal-types'
import ActivityTemplate from './partials/activity-template'
import HeaderTemplate from './partials/header-template'
// import InvestorProfileTemplate from './partials/investor-profile-template'
import OverviewTemplate from './partials/overview-template'
import DiversificationTemplate from './partials/diversification-template'
import SharpeRatioTemplate from './partials/sharpe-ratio-template'
import HoldingsTemplate from './partials/holdings-template'
import NoPortfolioTemplate from './partials/no-portfolio-template'

import BEMModule from 'utils/bem'
import styles from './styles.scss'
const bem = new BEMModule(styles)

const ActivitySectionWithPortfolio = withPublicPortfolio(ActivityTemplate)
const HeaderSection = withPublicPortfolio(HeaderTemplate)
const OverviewSection = withPublicPortfolio(OverviewTemplate)
const DiversificationSection = withPublicPortfolio(DiversificationTemplate)
const SharpeRatioSection = withPublicPortfolio(SharpeRatioTemplate)
const HoldingsSection = withPublicPortfolio(HoldingsTemplate)

const CompositionTemplate = (props) => (
    <React.Fragment>
        <DiversificationSection {...props} />
        <HoldingsSection {...props} />
    </React.Fragment>
)

const TabPanel = ({currentIndex, index, render: Component, ...rest}) => {
    if (currentIndex !== index) {
        return null
    }

    return <Component {...rest} />
}

TabPanel.propTypes = {
    currentIndex: PropTypes.number,
    index: PropTypes.number,
    render: PropTypes.func,
}

const tabLabels = [
    // {label: 'Investor Profile', value: 0},
    {label: 'Composition', value: 0},
    {label: 'Activity', value: 1},
    {label: 'Sharpe Ratio', value: 2},
]

const PortfolioShowcase = ({
    className,
    getOrders,
    getPortfolioSharpeTimeseries,
    getPortfolioTimeseries,
    getPublicPortfolio,
    getRankings,
    isOverlay,
    metrics,
    portfolio,
    portfolioId,
    portfolioValueTimeseries,
    securities,
    sharpeRatioTimeseries,
    showModal,
}) => {
    if (!portfolioId) {
        return null
    }

    if (portfolio?.status === requestStatuses.REJECTED) {
        return <NoPortfolioTemplate />
    }

    const [activeTabIndex, setActiveTabIndex] = useState(0)
    const [openedTableRow, setOpenedTableRow] = useState([0])

    const getSupplementalPortfolioData = ({portfolioId}) => {
        // When the main thread is idle, request for less critical data
        ric.requestIdleCallback(() => {
            if (!Object.keys(metrics?.sharpe?.allTime).length) {
                getRankings({portfolioId, sortOrder: null})
            }

            getOrders?.(
                {
                    portfolioId,
                    include: 'all',
                    isPublic: true,
                    status: orderStatuses.PROCESSED.value,
                },
                {alertOnError: false, overrideLoader: true}
            )
            getPortfolioTimeseries?.(
                {portfolioId},
                {alertOnError: false, overrideLoader: true}
            )

            if (
                !sharpeRatioTimeseries.hasOwnProperty(rankingPeriods.ALL_TIME) // eslint-disable-line no-prototype-builtins
            ) {
                getPortfolioSharpeTimeseries?.(
                    {portfolioId, period: rankingPeriods.ALL_TIME},
                    {alertOnError: false, overrideLoader: true}
                )
            }
        })
    }

    /**
     * Sets the context of the component to the portfolio specified
     */
    const setPortfolio = (portfolioId) => {
        if (portfolio?.id && portfolio?.holdings?.cash.length) {
            getSupplementalPortfolioData({portfolioId})
            return
        }

        getPublicPortfolio?.({portfolioId}).then(() => {
            getSupplementalPortfolioData({portfolioId})
        })
    }

    const setTab = ({index}) => {
        setActiveTabIndex(index)
    }

    const setActivityTableOpenedItem = useCallback((index) => {
        const rowIndex = index ? index : 0
        setOpenedTableRow([rowIndex])
    }, [])

    const showPortfolioDescription = () => {
        showModal?.({
            type: modalTypes.MODAL_PORTFOLIO_SHOWCASE_DESCRIPTION,
            portfolio,
            user: portfolio?.users?.[0],
            returnToPortfolioOnDismiss: isOverlay,
        })
    }

    useEffect(() => {
        // Retrieve all data related to given portfolioId
        if (portfolioId) {
            setPortfolio?.(portfolioId)
        }
    }, [portfolioId])

    const ActivitySection = useCallback(
        ActivitySectionWithPortfolio,
        [portfolio?.orders?.status, Object.keys(securities).length],
        openedTableRow[0]
    )

    const classes = bem.classNames('c-portfolio-showcase', className)
    const tabsWrapperClasses = bem.classNames(
        'c-portfolio-showcase__tabs-wrapper'
    )
    const tabsClasses = bem.classNames('c-portfolio-showcase__tabs')
    const tabsSliderClasses = bem.classNames(
        'c-portfolio-showcase__tabs-slider'
    )
    const tabItemClasses = bem.classNames('c-portfolio-showcase__tab-item')
    const tabItemActiveClasses = bem.classNames(
        'c-portfolio-showcase__tab-item--active'
    )

    return (
        <Flex
            align="center"
            className={classes}
            direction="column"
            justify="center"
        >
            <Provider
                value={{
                    metrics,
                    portfolio,
                    timeseries: portfolioValueTimeseries,
                }}
            >
                <HeaderSection />

                <OverviewSection showDescription={showPortfolioDescription} />

                <div className={tabsWrapperClasses}>
                    <TabsWithSlider
                        activeIndex={activeTabIndex}
                        className={tabsClasses}
                        itemActiveClassName={tabItemActiveClasses}
                        itemClassName={tabItemClasses}
                        items={tabLabels}
                        onItemSelected={setTab}
                    >
                        <TabsWithSlider.Items />
                        <TabsWithSlider.Slider className={tabsSliderClasses} />
                    </TabsWithSlider>
                </div>

                {/* <TabPanel currentIndex={activeTabIndex} index={0} render={InvestorProfileTemplate} /> */}

                <TabPanel
                    currentIndex={activeTabIndex}
                    index={0}
                    render={CompositionTemplate}
                    securities={securities}
                />

                <TabPanel
                    currentIndex={activeTabIndex}
                    index={1}
                    onItemClose={setActivityTableOpenedItem}
                    onItemOpen={setActivityTableOpenedItem}
                    openedItem={openedTableRow}
                    onPageChange={getOrders}
                    orders={portfolio?.orders}
                    render={ActivitySection}
                    securities={securities}
                />

                <TabPanel
                    currentIndex={activeTabIndex}
                    index={2}
                    render={SharpeRatioSection}
                    timeseries={sharpeRatioTimeseries}
                />
            </Provider>
        </Flex>
    )
}

PortfolioShowcase.propTypes = {
    portfolioId: PropTypes.string.isRequired,
    className: PropTypes.string,
    getOrders: PropTypes.func,
    getPortfolioSharpeTimeseries: PropTypes.func,
    getPortfolioTimeseries: PropTypes.func,
    getPublicPortfolio: PropTypes.func,
    getRankings: PropTypes.func,
    isOverlay: PropTypes.bool,
    metrics: PropTypes.object,
    orders: PropTypes.any,
    portfolio: PropTypes.object,
    portfolioValueTimeseries: PropTypes.object,
    securities: PropTypes.object,
    sharpeRatioTimeseries: PropTypes.object,
    showModal: PropTypes.func,
}

export default PortfolioShowcase
