/* Prettier vs Eslint error */
/* eslint-disable indent */
import React, {useEffect, useMemo} from 'react'
import PropTypes from 'prop-types'
import {makePrimaryMetrics} from './helpers'
import {getEngagementScore} from 'utils/portfolio'
import {hasEngagementRequirements} from 'utils/course'
import {HISTOGRAM_MAP} from './constants'
import BEMModule from 'utils/bem'
import engagementRequirements from 'global/constants/engagement-requirements'
import requestStatuses from 'common-fe/constants/request-statuses'
import styles from './styles.scss'

import CourseMetric from 'components/card/course-metric'
import CoursePortfolioGoal from 'components/card/course-portfolio-goal'
import CourseTotalScore from 'components/card/course-total-score'
import CourseWarning from 'components/card/course-warning'
import Layout from 'components/layout'

const bem = new BEMModule(styles)

const {
    MAX_CASH_PERCENTAGE,
    MIN_BOND_TRADES,
    MIN_EQUITY_TRADES,
    MIN_OPTION_TRADES,
    MIN_RATIONALES,
    MIN_SHORT_TRADES,
    MIN_HOLDINGS,
    MIN_TRADES,
} = engagementRequirements

const CourseOverviewPage = ({
    course,
    getCourseMetrics,
    getRankings,
    policy,
    portfolio,
    ranking,
}) => {
    const {isOwner, isParticipant} = policy

    useEffect(() => {
        const {id: portfolioId} = portfolio || {}
        const {id: courseId} = course
        if (portfolioId) {
            getRankings?.({
                portfolioId,
                courseId,
                sortOrder: null,
            })
            getCourseMetrics?.({
                courseId: course.id,
                metricIds: [
                    'diversification',
                    'engagement',
                    'sharpe',
                    'return',
                    'volatility',
                ],
            })
        }

        // As an owner of the course, we want to see all the histogram data
        if (isOwner && !course?.metrics) {
            // Re-fetch course histogram data information if needed
            getCourseMetrics?.({courseId: course.id, detailed: true})
        }
    }, [course.id, portfolio?.id, getCourseMetrics, getRankings])

    const hasEngagement = hasEngagementRequirements(course)

    const metrics = useMemo(() => {
        if (isOwner || !isParticipant) {
            return []
        }

        const primaryMetrics = makePrimaryMetrics({
            portfolio,
            course,
            ranking,
        })

        let engagementMetrics = []

        if (portfolio?.metrics?.engagement) {
            const {breakdown} = getEngagementScore({
                goals: course,
                results: portfolio.metrics.engagement,
            })

            /* eslint-disable max-len */
            engagementMetrics = [
                {
                    label: 'Holdings',
                    goal: breakdown[MIN_HOLDINGS.value].goal,
                    value: breakdown[MIN_HOLDINGS.value].result,
                    render: CoursePortfolioGoal,
                },
                {
                    label:
                        typeof course[MAX_CASH_PERCENTAGE.value] === 'number'
                            ? `% Cash Invested (${(
                                  100 - course[MAX_CASH_PERCENTAGE.value]
                              ).toFixed(2)}%)`
                            : '% Cash Invested',
                    goal: breakdown[MAX_CASH_PERCENTAGE.value].goal,
                    value:
                        typeof breakdown[MAX_CASH_PERCENTAGE.value].result ===
                        'number'
                            ? (
                                  100 -
                                  breakdown[MAX_CASH_PERCENTAGE.value].result *
                                      100
                              ).toFixed(2)
                            : 100,
                    completionValue: 1,
                    render: CoursePortfolioGoal,
                },
                {
                    label: 'Equity Trades',
                    goal: breakdown[MIN_EQUITY_TRADES.value].goal,
                    value: breakdown[MIN_EQUITY_TRADES.value].result,
                    render: CoursePortfolioGoal,
                },
                {
                    label: 'Bond Trades',
                    goal: breakdown[MIN_BOND_TRADES.value].goal,
                    value: breakdown[MIN_BOND_TRADES.value].result,
                    render: CoursePortfolioGoal,
                },
                {
                    label: 'Option Trades',
                    goal: breakdown[MIN_OPTION_TRADES.value].goal,
                    value: breakdown[MIN_OPTION_TRADES.value].result,
                    render: CoursePortfolioGoal,
                },
                {
                    label: 'Short Trades',
                    goal: breakdown[MIN_SHORT_TRADES.value].goal,
                    value: breakdown[MIN_SHORT_TRADES.value].result,
                    render: CoursePortfolioGoal,
                },
                {
                    label: 'Rationales',
                    goal: breakdown[MIN_RATIONALES.value].goal,
                    value: breakdown[MIN_RATIONALES.value].result,
                    render: CoursePortfolioGoal,
                },
            ]
        }

        return [...primaryMetrics, ...engagementMetrics]
    }, [
        course.metrics,
        portfolio?.metrics,
        ranking?.allTime,
        isOwner,
        isParticipant,
    ])

    const histograms = useMemo(() => {
        const charts = []

        if (!isOwner) {
            return charts
        }

        charts.push({
            ...HISTOGRAM_MAP.DIVERSIFICATION,
            histogram:
                course.metrics?.[HISTOGRAM_MAP.DIVERSIFICATION.key] || [],
        })
        charts.push({
            ...HISTOGRAM_MAP.SHARPE,
            histogram: course.metrics?.[HISTOGRAM_MAP.SHARPE.key] || [],
        })
        charts.push({
            ...HISTOGRAM_MAP.RETURN,
            histogram: course.metrics?.[HISTOGRAM_MAP.RETURN.key] || [],
        })

        charts.push({
            ...HISTOGRAM_MAP.VOLATILITY,
            histogram: course.metrics?.[HISTOGRAM_MAP.VOLATILITY.key] || [],
        })

        if (!hasEngagement || !course.metrics?.courseEngagementMetrics) {
            return charts
        }

        charts.push({
            ...HISTOGRAM_MAP.ENGAGEMENT,
            histogram: course.metrics[HISTOGRAM_MAP.ENGAGEMENT.key] || [],
        })

        return Object.entries(course.metrics.courseEngagementMetrics).reduce(
            (result, [req, goal]) => {
                const {afterLabel, key, title, legend, ...rest} = HISTOGRAM_MAP[
                    req
                ]

                if (req === MAX_CASH_PERCENTAGE.value) {
                    // Clamp values between 0 and 100 with Math.max and Math.min
                    let isClamped = false
                    const cashMetrics = course.metrics[key].map((val) => {
                        const invertedValue = 100 - val * 100
                        if (invertedValue > 100) {
                            isClamped = true
                        }

                        return Math.max(Math.min(invertedValue, 100), 0)
                    })
                    result.push({
                        afterLabel,
                        isClamped,
                        title,
                        legend,
                        histogram: cashMetrics,
                        passing: 100 - goal,
                        ...rest,
                    })
                } else if (req !== MIN_TRADES.value) {
                    result.push({
                        title,
                        legend,
                        histogram: course.metrics[key],
                        passing: goal,
                        ...rest,
                    })
                }

                return result
            },
            charts
        )
    }, [isOwner, hasEngagement, course.metrics])

    const isShowingTotalScore =
        !isOwner && isParticipant && course.hasRankingWeights

    const gridClassNames = bem.classNames('c-course-overview__grid')
    const jumboClassNames = bem.classNames('c-course-overview__jumbo')

    return (
        <Layout.Section hasMobilePadding>
            <main className={gridClassNames}>
                {isShowingTotalScore && (
                    <CourseTotalScore
                        className={jumboClassNames}
                        weights={course.rankingWeights}
                        value={ranking?.total?.scoreDisplay || `- -`}
                    />
                )}

                {metrics.map((metric, i) => {
                    if (!metric) {
                        return null
                    }
                    const {render: Component, ...props} = metric
                    return <Component key={`metric-card-${i}`} {...props} />
                })}

                {histograms.map((histogram) => (
                    <CourseMetric
                        key={histogram.title}
                        status={
                            course?.metrics?.status || requestStatuses.PENDING
                        }
                        {...histogram}
                    />
                ))}

                {course.restrictDayTrading && (
                    <CourseWarning
                        title="Day Trading Disabled"
                        description="The moderators of this challange have disabled day trading. You can not trade the same security twice in one day. For example you can not buy AMZN in the morning and sell it before market close."
                    />
                )}
            </main>
        </Layout.Section>
    )
}

CourseOverviewPage.propTypes = {
    course: PropTypes.object,
    getCourseMetrics: PropTypes.func,
    getRankings: PropTypes.func,
    metrics: PropTypes.object,
    policy: PropTypes.object,
    portfolio: PropTypes.object,
    ranking: PropTypes.object,
}

export default CourseOverviewPage
