import InjectMessage from '@/actionlog/InjectMessage'
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 { NonIdealState, Spinner, SpinnerSize } from '@blueprintjs/core'
import Manager from '@inject/graphql/components/Manager'
import type { ActionLog } from '@inject/graphql/fragments/ActionLog.generated'
import ErrorMessage from '@inject/shared/components/ErrorMessage'
import NotificationDropdown from '@inject/shared/notification/NotificationDropdown'
import type { FC, PropsWithChildren } from 'react'
import { Suspense, useCallback, useMemo } from 'react'
import { useLocation } from 'react-router-dom'
import TraineeEmailFormOverlay from '../../email/EmailFormOverlay/TraineeEmailFormOverlay'
import ChannelButton from '../ChannelButton'
import { contentClass, viewClass } from '../classes'
import useTraineeViewData from './useTraineeViewData'

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

const TraineeView: FC<TraineeViewProps> = ({
  children,
  teamId,
  exerciseId,
  selectedThreadId,
}) => {
  const { hide: hideLeftBar, node: hideButton } = useHideButton()
  const loc = useLocation()

  const {
    loading,
    error,
    team,
    showExerciseTime,
    emailsEnabled,
    channels,
    loopRunning,
  } = useTraineeViewData({ teamId, exerciseId })

  const getPopup = useCallback(
    (actionLog: ActionLog) => (
      <InjectMessage
        actionLog={actionLog}
        exerciseId={exerciseId}
        teamId={teamId}
        inInstructor={false}
        fill
      />
    ),
    [exerciseId, teamId]
  )

  const sections: Section[] = [
    {
      node: (
        <Status
          showTime={showExerciseTime}
          small={hideLeftBar}
          exerciseRunning={loopRunning}
          team={team}
          hideLabel={hideLeftBar}
        />
      ),
    },

    {
      name: 'Options',
      node: (
        <>
          {hideButton}
          <NotificationDropdown hideLabel={hideLeftBar} fill />
          <ExitButton hideLabel={hideLeftBar} />
        </>
      ),
    },
    {
      name: 'Channels',
      node: (
        <>
          {loading ? (
            <Spinner size={SpinnerSize.SMALL} />
          ) : (
            channels.map(channel => (
              <ChannelButton
                key={channel.id}
                channel={channel}
                exerciseId={exerciseId}
                linkTo='trainee'
                pathname={loc.pathname}
                teamId={teamId}
                hideLabel={hideLeftBar}
              />
            ))
          )}
        </>
      ),
    },
  ]

  const content = useMemo(() => {
    if (loading) {
      return <Spinner />
    }
    if (error) {
      return (
        <ErrorMessage>
          <h1>Error occurred!</h1>
          <p>{error.message}</p>
        </ErrorMessage>
      )
    }
    if (!loopRunning) {
      return (
        <NonIdealState
          icon='disable'
          title='Exercise not running'
          description='The exercise is not running, please contact your instructor.'
        />
      )
    }
    return <Suspense fallback={<Spinner />}>{children}</Suspense>
  }, [children, error, loading, loopRunning])

  return (
    <>
      {emailsEnabled && (
        <TraineeEmailFormOverlay teamId={teamId} exerciseId={exerciseId} />
      )}
      <Manager getPopup={getPopup} selectedThreadId={selectedThreadId} />

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

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

export default TraineeView
