import { EmailSelection } from '@/analyst/utilities'
import { useHideSidebarValue } from '@/clientsettings/vars/hidesidebar'
import ExitButton from '@/components/ExitButton'
import MoveTimeButton from '@/components/MoveTimeButton'
import type { Section } from '@/components/Sidebar'
import Sidebar from '@/components/Sidebar'
import HideButton from '@/components/Sidebar/HideSidebarButton'
import Status from '@/components/Status'
import InstructorEmailFormOverlay from '@/email/EmailFormOverlay/InstructorEmailFormOverlay'
import useMailToRef from '@/hooks/useMailToRef'
import InstructorInject from '@/instructor/InstructorInject'
import InstructorTeamSelector from '@/instructor/InstructorTeamSelector'
import TeamListVertical from '@/instructor/InstructorTeamSelector/TeamListVertical'
import LearningObjectivesButton from '@/instructor/LearningObjectives/LearningObjectivesButton'
import { useNavigate } from '@/router'
import { Spinner, SpinnerSize } from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import { useLoopStatus } from '@inject/graphql/utils/useExerciseLoopStatusSubscription'
import CenteredSpinner from '@inject/shared/components/CenteredSpinner'
import ErrorMessage from '@inject/shared/components/ErrorMessage'
import type { FC } from 'react'
import { memo, Suspense, useMemo } from 'react'
import { matchPath, Outlet, useMatch } from 'react-router-dom'
import ChannelButton from '../ChannelButton'
import {
  contentClass,
  sidebarClass,
  sidebarClassCompact,
  viewClass,
} from '../classes'
import MilestonesButton from './MilestoneButton'
import OverviewButton from './OverviewButton'
import TeamOverviewButton from './TeamOverviewButton'
import TeamTabs from './TeamTabs'
import useInstructorViewData from './useInstructorViewData'

interface InstructorViewProps {
  teamId?: string
  exerciseId?: string
}

const InstructorView: FC<InstructorViewProps> = ({ teamId, exerciseId }) => {
  const contentRef = useMailToRef()
  const hideLeftBar = useHideSidebarValue()
  const nav = useNavigate()
  const match = useMatch('/instructor/:exerciseId/select')
  const { running } = useLoopStatus()

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

  const stickySections: Section[] = [
    {
      id: 'status',
      node: (
        <div
          className={cx({
            [css`
              display: flex;
              align-items: center;
              justify-content: space-around;
            `]: !hideLeftBar,
          })}
        >
          <Status showTime small={hideLeftBar} hideLabel={hideLeftBar} />
        </div>
      ),
    },
  ]
  const sections: Section[] = [
    {
      id: 'options',
      name: 'Options',
      node: (
        <>
          <HideButton />
          {exerciseId && (
            <OverviewButton exerciseId={exerciseId} hideLabel={hideLeftBar} />
          )}
          <MoveTimeButton
            hideLabel={hideLeftBar}
            exerciseId={exerciseId}
            disabledTitle={
              exerciseId ? undefined : 'A team has to be selected to move time'
            }
          />
          {exerciseId && !teamId && (
            <MilestonesButton
              exerciseId={exerciseId}
              teamId={teamId}
              hideLabel={hideLeftBar}
            />
          )}
          <InstructorInject
            teamId={teamId}
            exerciseId={exerciseId}
            hideLabel={hideLeftBar}
          />
          <InstructorTeamSelector
            exerciseId={exerciseId}
            hideLabel={hideLeftBar}
          />
          <ExitButton hideLabel={hideLeftBar} />
        </>
      ),
    },
    ...(exerciseId && teamId
      ? [
          {
            id: 'teamsettings',
            name: 'Team',
            node: (
              <>
                <TeamOverviewButton
                  exerciseId={exerciseId}
                  teamId={teamId}
                  hideLabel={hideLeftBar}
                />
                <MilestonesButton
                  exerciseId={exerciseId}
                  teamId={teamId}
                  hideLabel={hideLeftBar}
                />
                <LearningObjectivesButton
                  teamId={teamId}
                  exerciseId={exerciseId}
                  hideLabel={hideLeftBar}
                />
              </>
            ),
          },
        ]
      : []),
    ...(exerciseId && teamId
      ? [
          {
            id: 'channels',
            name: 'Channels',
            node: loading ? (
              <Spinner size={SpinnerSize.SMALL} />
            ) : (
              <>
                {channels.map(channel => (
                  <ChannelButton
                    key={channel.id}
                    channel={channel}
                    exerciseId={exerciseId}
                    linkTo='instructor'
                    teamId={teamId}
                    hideLabel={hideLeftBar}
                  />
                ))}
              </>
            ),
          },
        ]
      : []),
    ...(exerciseId
      ? [
          {
            id: 'teams',
            name: 'Teams',
            node: (
              <TeamListVertical
                hideLabel={hideLeftBar}
                exerciseId={exerciseId}
              />
            ),
          },
        ]
      : []),
  ]

  const content = useMemo(() => {
    if (loading) {
      return <CenteredSpinner />
    }
    if (error) {
      return (
        <ErrorMessage>
          <h1>Error occurred!</h1>
          <p>{error.message}</p>
        </ErrorMessage>
      )
    }
    return (
      <Suspense fallback={<CenteredSpinner />}>
        <Outlet />
      </Suspense>
    )
  }, [error, loading])

  return (
    <>
      {emailsEnabled && teamId && exerciseId && running && (
        <InstructorEmailFormOverlay
          teamId={teamId}
          exerciseId={exerciseId}
          onSuccess={threadId =>
            threadId &&
            !matchPath(
              {
                path: '/instructor/:exerciseId/:teamId/email',
                end: false,
              },
              window.location.pathname
            ) &&
            nav('/instructor/:exerciseId/:teamId/email/:tab/:threadId', {
              params: {
                exerciseId,
                tab: EmailSelection.SENT,
                teamId,
                threadId,
              },
              state: {
                autoRedirect: true,
              },
            })
          }
        />
      )}

      <div className={viewClass}>
        <Sidebar
          onClickLogo={
            exerciseId
              ? () => {
                  nav('/instructor/:exerciseId', {
                    params: {
                      exerciseId,
                    },
                  })
                }
              : undefined
          }
          className={cx({
            [sidebarClass]: !hideLeftBar,
            [sidebarClassCompact]: hideLeftBar,
          })}
          position='left'
          sections={sections}
          stickySections={stickySections}
          hideNames={hideLeftBar}
          showLogo
        />

        <div style={{ position: 'relative', width: '100%' }}>
          <div className={contentClass} id='contentView' ref={contentRef}>
            {exerciseId && !match && (
              <TeamTabs exerciseId={exerciseId} teamId={teamId} />
            )}
            {content}
          </div>
        </div>

        <div id='toolPanel' />
        <div id='rightPanel' />
      </div>
    </>
  )
}

export default memo(InstructorView)
