import React, {useCallback, useEffect, useMemo, useState} from 'react'
import PropTypes from 'prop-types'
import hoistNonReactStatics from 'hoist-non-react-statics'
import TabsWithSlider from 'react-uikit/tabs/with-slider'
import Layout from 'components/layout'
import Header from 'components/stock-header'
import CompanyFinancials from 'components/company-financials'
import StockOverview from 'components/stock-overview'
import PageNotFound from 'containers/pages/not-found'
import modalTypes from 'containers/modal-manager/modal-types'
import metricIds from 'global/constants/metric-ids'
import BEMModule from 'utils/bem'
import {Provider, withStock} from './context'
import styles from './styles.scss'

const bem = new BEMModule(styles)
const StockHeader = withStock(Header)

const StockProfilePage = ({
    exchange,
    financials,
    getFundamentals,
    getSecurity,
    getSecurityTimeseries,
    getSecurityIntradayMarketValueTimeseries,
    security,
    securityId,
    showModal,
    subscribeToSecurity,
    timeseries,
    unsubscribeToSecurity,
}) => {
    const [activeTabIndex, setActiveTabIndex] = useState(0)
    const hasSecurity = Boolean(security?.id)
    const hasTimeseries = Boolean(timeseries)
    const hasFinancials = Boolean(financials)

    useEffect(() => {
        if (!securityId) {
            return
        }

        getSecurity?.({securityId}, {overrideLoader: hasSecurity})
        getSecurityTimeseries?.(
            {securityId, timeseriesType: metricIds.MARKET_VALUE},
            {overrideLoader: hasTimeseries}
        )
    }, [
        securityId,
        getSecurity,
        getSecurityTimeseries,
        hasSecurity,
        hasTimeseries,
    ])

    // Handle real-time subscriptions when the security resolves
    useEffect(() => {
        if (security?.id) {
            subscribeToSecurity?.({
                exchange: security?.exchange,
                securityId: security?.id,
            })
        }

        return () => {
            if (security?.id) {
                unsubscribeToSecurity?.({
                    exchange: security?.exchange,
                    securityId: security?.id,
                })
            }
        }
    }, [
        security?.id,
        security?.exchange,
        subscribeToSecurity,
        unsubscribeToSecurity,
    ])

    useEffect(() => {
        if (activeTabIndex === 1) {
            getFundamentals?.(
                {
                    exchange: security?.exchange,
                    ticker: security?.ticker,
                },
                {overrideLoader: hasFinancials}
            )
        }
    }, [
        activeTabIndex,
        getFundamentals,
        hasFinancials,
        security?.exchange,
        security?.ticker,
    ])

    const childContext = useMemo(
        () => ({
            exchange,
            financials,
            stock: security,
            timeseries,
            getSecurityIntradayMarketValueTimeseries: (startDate) => {
                return getSecurityIntradayMarketValueTimeseries?.(
                    {securityId, startDate},
                    {alertOnError: false, overrideLoader: true}
                )
            },
        }),
        [
            exchange,
            financials,
            getSecurityIntradayMarketValueTimeseries,
            security,
            securityId,
            timeseries,
        ]
    )

    const onTabSelected = useCallback(
        ({index: activeIndex}) => setActiveTabIndex(activeIndex),
        [setActiveTabIndex]
    )
    const openStockOrder = useCallback(
        () => showModal?.({securityId, type: modalTypes.MODAL_ORDER}),
        [securityId]
    )

    if (!securityId || (!hasSecurity && security.error)) {
        return <PageNotFound />
    }

    // Not yet resolved, so we have nothing to render.
    if (!hasSecurity) {
        return null
    }

    const classes = bem.classNames('c-stock-profile-page')
    const tabsClasses = bem.classNames('c-stock-profile-page__tabs')
    const tabItemClasses = bem.classNames('c-stock-profile-page__tab-item')
    const tabSliderClasses = bem.classNames('c-stock-profile-page__tab-slider')
    const tabViewClasses = bem.classNames('c-stock-profile-page__tab-view')
    const hrClasses = bem.classNames('c-stock-profile-page__hr')
    const activeTabClasses = bem.classNames(
        'c-stock-profile-page__tab-item--active'
    )
    const TabView = StockProfilePage.tabViews[activeTabIndex].view

    return (
        <Layout.Main className={classes}>
            <Provider value={childContext}>
                <StockHeader openStockOrder={openStockOrder} />
                <hr className={hrClasses} />
                <TabsWithSlider
                    activeIndex={activeTabIndex}
                    className={tabsClasses}
                    items={StockProfilePage.tabViews}
                    itemClassName={tabItemClasses}
                    itemActiveClassName={activeTabClasses}
                    onItemSelected={onTabSelected}
                >
                    <TabsWithSlider.Items />
                    <TabsWithSlider.Slider className={tabSliderClasses} />
                </TabsWithSlider>
                <div className={tabViewClasses}>
                    <TabView />
                </div>
            </Provider>
        </Layout.Main>
    )
}

StockProfilePage.pageTitle = 'Stock Profile'
StockProfilePage.tabViews = [
    {
        label: 'Overview',
        value: 'overview-tab',
        view: withStock(StockOverview),
    },
    {
        label: 'Financials',
        value: 'financials-tab',
        view: withStock(CompanyFinancials),
    },
]

StockProfilePage.propTypes = {
    getFundamentals: PropTypes.func.isRequired,
    getSecurity: PropTypes.func.isRequired,
    getSecurityIntradayMarketValueTimeseries: PropTypes.func.isRequired,
    getSecurityTimeseries: PropTypes.func.isRequired,
    exchange: PropTypes.shape({
        message: PropTypes.shape({
            time: PropTypes.string,
            status: PropTypes.string,
        }),
    }),
    financials: PropTypes.object,
    security: PropTypes.object,
    securityId: PropTypes.string,
    showModal: PropTypes.func,
    subscribeToSecurity: PropTypes.func,
    timeseries: PropTypes.object,
    unsubscribeToSecurity: PropTypes.func,
    updateTitle: PropTypes.func,
}

export default hoistNonReactStatics(
    React.memo(StockProfilePage),
    StockProfilePage
)
