import ExitButton from '@/components/ExitButton'
import type { Section } from '@/components/Sidebar'
import Sidebar from '@/components/Sidebar'
import useHideButton from '@/components/Sidebar/useHideButton'
import Status from '@/components/Status'
import InstructorEmailFormOverlay from '@/email/EmailFormOverlay/InstructorEmailFormOverlay'
import InstructorInject from '@/instructor/InstructorInject'
import InstructorMilestones from '@/instructor/InstructorMilestones'
import InstructorTeamSelector from '@/instructor/InstructorTeamSelector'
import LearningObjectivesButton from '@/instructor/LearningObjectives/LearningObjectivesButton'
import { NonIdealState, Spinner, SpinnerSize } from '@blueprintjs/core'
import Manager from '@inject/graphql/components/Manager'
import { useSubscriptionContext } from '@inject/graphql/context/SubscriptionContext'
import ErrorMessage from '@inject/shared/components/ErrorMessage'
import NotificationDropdown from '@inject/shared/notification/NotificationDropdown'
import type { FC, PropsWithChildren } from 'react'
import { Suspense, memo, useEffect, useMemo } from 'react'
import { useLocation } from 'react-router-dom'
import ChannelButton from '../ChannelButton'
import { contentClass, viewClass } from '../classes'
import useInstructorViewData from './useInstructorViewData'
import useMilestonesButton from './useMilestonesButton'

interface InstructorViewProps extends PropsWithChildren {
  teamId?: string
  exerciseId?: string
  selectedThreadId?: string
}

const InstructorView: FC<InstructorViewProps> = ({
  children,
  teamId,
  exerciseId,
  selectedThreadId,
}) => {
  const loc = useLocation()

  const { hide: hideLeftBar, node: hideButton } = useHideButton()
  const { open: milestonesOpen, node: milestonesButton } = useMilestonesButton({
    hideLabel: hideLeftBar,
    disabled: !teamId,
  })

  const { enableInstructorContext, disableInstructorContext } =
    useSubscriptionContext()
  useEffect(() => {
    enableInstructorContext()
    return disableInstructorContext
  })

  const { loading, error, loopRunning, channels, emailsEnabled } =
    useInstructorViewData({
      exerciseId,
    })

  const sections: Section[] = [
    {
      node: (
        <Status showTime small={hideLeftBar} exerciseRunning={loopRunning} />
      ),
    },
    {
      name: 'Options',
      node: (
        <>
          {hideButton}
          <NotificationDropdown hideLabel={hideLeftBar} fill />
          {milestonesButton}
          <InstructorInject
            teamId={teamId}
            exerciseId={exerciseId}
            hideLabel={hideLeftBar}
          />
          <LearningObjectivesButton
            teamId={teamId}
            exerciseId={exerciseId}
            hideLabel={hideLeftBar}
            pathname={loc.pathname}
          />
          <ExitButton hideLabel={hideLeftBar} />
        </>
      ),
    },
    {
      name: 'Teams',
      node: <InstructorTeamSelector hideLabel={hideLeftBar} teamId={teamId} />,
    },
    ...(exerciseId && teamId
      ? [
          {
            name: 'Channels',
            node: loading ? (
              <Spinner size={SpinnerSize.SMALL} />
            ) : (
              <>
                {channels.map(channel => (
                  <ChannelButton
                    key={channel.id}
                    channel={channel}
                    exerciseId={exerciseId}
                    linkTo='instructor'
                    pathname={loc.pathname}
                    teamId={teamId}
                    hideLabel={hideLeftBar}
                  />
                ))}
              </>
            ),
          },
        ]
      : []),
  ]

  const milestoneSections: Section[] = teamId
    ? [
        {
          name: 'Reached',
          node: <InstructorMilestones teamId={teamId} reached />,
        },
        {
          name: 'Unreached',
          node: <InstructorMilestones teamId={teamId} reached={false} />,
        },
      ]
    : []

  const content = useMemo(() => {
    if (loading) {
      return <Spinner />
    }
    if (error) {
      return (
        <ErrorMessage>
          <h1>Error occurred!</h1>
          <p>{error.message}</p>
        </ErrorMessage>
      )
    }
    if (!teamId) {
      return (
        <NonIdealState
          icon='search'
          title='No team selected'
          description='Select a team to interact with'
        />
      )
    }
    if (!loopRunning) {
      return (
        <NonIdealState
          icon='disable'
          title='Exercise not running'
          description='The selected exercise is not running'
        />
      )
    }
    return <Suspense fallback={<Spinner />}>{children}</Suspense>
  }, [children, error, loading, loopRunning, teamId])

  return (
    <>
      {emailsEnabled && teamId && exerciseId && (
        <InstructorEmailFormOverlay teamId={teamId} exerciseId={exerciseId} />
      )}
      {
        // TODO: I've detected performance issues there, but it could be just me. Otherwise I would just move this to it's former place..
      }
      <Manager teamId={teamId} selectedThreadId={selectedThreadId} />

      <div className={viewClass}>
        <Sidebar
          position='left'
          sections={sections}
          hideNames={hideLeftBar}
          showLogo
        />

        <div className={contentClass}>{content}</div>

        {milestonesOpen && teamId && (
          <Sidebar
            position='right'
            title='Milestones'
            sections={milestoneSections}
          />
        )}
      </div>
    </>
  )
}

export default memo(InstructorView)
