import { useHideSidebarValue } from '@/clientsettings/vars/hidesidebar'
import type { Section } from '@/components/Sidebar'
import Sidebar from '@/components/Sidebar'
import HideButton from '@/components/Sidebar/HideSidebarButton'
import Navbar from '@/editor/Navbar'
import { NAVIGATION_CONTENT } from '@/editor/assets/navigationContent'
import { db } from '@/editor/indexeddb/db'
import {
  areActivitiesSpecified,
  areInjectsSpecified,
  doInjectsHaveCorrectConditions,
  doToolResponsesHaveCorrectConditions,
  doToolsHaveResponses,
} from '@/editor/indexeddb/operations'
import useEditorAccessStorage from '@/editor/useEditorAccessStorage'
import useEditorStorage from '@/editor/useEditorStorage'
import useGitlabStorage from '@/editor/useGitlabStorage'
import { useNavigate } from '@/router'
import { Button } from '@blueprintjs/core'
import { css, cx } from '@emotion/css'
import { useLiveQuery } from 'dexie-react-hooks'
import { isEmpty } from 'lodash'
import type { FC, PropsWithChildren } from 'react'
import { memo, useEffect, useMemo, useState } from 'react'
import { sidebarClass, sidebarClassCompact } from '../classes'

const definitionName = css`
  margin: 0.75rem 0 1rem 1rem;
  max-width: 13rem;
  text-overflow: ellipsis;
  overflow: hidden;
  white-space: nowrap;
`

const definitionNameButton = css`
  max-width: 15rem;
`

const EditorView: FC<PropsWithChildren> = ({ children }) => {
  const [access, setAccess] = useEditorAccessStorage()
  const [config] = useEditorStorage()
  const [gitlabConfig] = useGitlabStorage()
  const nav = useNavigate()

  const learningActivitiesCount = useLiveQuery(
    () => db.learningActivities.count(),
    [],
    0
  )
  const injectsCount = useLiveQuery(() => db.injectInfos.count(), [], 0)
  const activitiesSpecified = useLiveQuery(
    () => areActivitiesSpecified(),
    [],
    false
  )
  const injectsSpecified = useLiveQuery(() => areInjectsSpecified(), [], false)
  const injectsHaveCorrectConditions = useLiveQuery(
    () => doInjectsHaveCorrectConditions(),
    [],
    false
  )
  const toolsHaveResponses = useLiveQuery(
    () => doToolsHaveResponses(),
    [],
    false
  )
  const toolsHaveCorrectConditions = useLiveQuery(
    () => doToolResponsesHaveCorrectConditions(),
    [],
    false
  )

  const [allIntroChecked, setAllIntroChecked] = useState(
    config?.introChecked?.every(Boolean) || false
  )
  const [allConclusionChecked, setAllConclusionChecked] = useState(
    config?.conclusionChecked?.every(Boolean) || false
  )
  const [allExerciseInformationFilled, setAllExerciseInformationFilled] =
    useState(
      !isEmpty(config?.name) &&
        !isEmpty(config?.description) &&
        !isEmpty(config?.trainee)
    )

  useEffect(() => {
    setAllIntroChecked(config?.introChecked?.every(Boolean) || false)
  }, [config?.introChecked])

  useEffect(() => {
    setAllExerciseInformationFilled(
      !isEmpty(config?.name) &&
        !isEmpty(config?.description) &&
        !isEmpty(config?.trainee)
    )
  }, [config?.name, config?.description, config?.trainee])

  useEffect(() => {
    setAllConclusionChecked(config?.conclusionChecked?.every(Boolean) || false)
  }, [config?.conclusionChecked])

  useEffect(() => {
    setAccess(prev => ({
      ...prev,
      introductionFilled: allIntroChecked,
      exerciseInformationFilled:
        allExerciseInformationFilled && prev?.introductionFilled,
      objectivesFilled:
        learningActivitiesCount > 0 && prev?.exerciseInformationFilled,
      injectsFilled: injectsCount > 0 && prev?.objectivesFilled,
      specificationsFilled:
        activitiesSpecified &&
        injectsSpecified &&
        injectsHaveCorrectConditions &&
        toolsHaveResponses &&
        toolsHaveCorrectConditions &&
        prev?.injectsFilled,
      finalInformationFilled:
        (config?.exerciseDuration || 0) > 0 && prev?.specificationsFilled,
      conclusionFilled: allConclusionChecked && prev?.finalInformationFilled,
    }))
  }, [
    access?.introductionFilled,
    access?.exerciseInformationFilled,
    access?.objectivesFilled,
    access?.injectsFilled,
    access?.specificationsFilled,
    access?.finalInformationFilled,
    allIntroChecked,
    allExerciseInformationFilled,
    learningActivitiesCount,
    injectsCount,
    activitiesSpecified,
    toolsHaveResponses,
    injectsSpecified,
    injectsHaveCorrectConditions,
    toolsHaveCorrectConditions,
    config?.exerciseDuration,
    allConclusionChecked,
  ])

  const hide = useHideSidebarValue()

  const sections: Section[] = useMemo(
    () => [
      {
        id: 'options',
        name: 'Options',
        node: (
          <>
            <HideButton />
            <Button
              icon='cross-circle'
              intent='danger'
              alignText='left'
              fill
              minimal
              text={!hide && 'Exit'}
              title='Exit'
              onClick={() => nav('/editor')}
            />
          </>
        ),
      },
      {
        id: 'definition',
        name: 'Definition',
        node:
          !hide &&
          (gitlabConfig?.project ? (
            <Button
              type='button'
              text={gitlabConfig.project.name}
              onClick={() => nav('/editor/definitions')}
              alignText='left'
              minimal
              fill
              ellipsizeText
              className={definitionNameButton}
            />
          ) : (
            <p className={definitionName}>
              {access?.exerciseInformationFilled
                ? config?.name
                : 'New definition'}
            </p>
          )),
      },
      {
        id: 'navigation',
        name: NAVIGATION_CONTENT.title,
        node: !hide && <Navbar />,
      },
    ],
    [
      hide,
      access?.exerciseInformationFilled,
      config?.name,
      gitlabConfig?.project,
    ]
  )

  return (
    <>
      <div style={{ height: '100%', display: 'flex' }}>
        <Sidebar
          position='left'
          sections={sections}
          hideNames={hide}
          showLogo
          className={cx({
            [sidebarClass]: !hide,
            [sidebarClassCompact]: hide,
          })}
        />

        <div style={{ overflow: 'auto', flex: 1 }}>{children}</div>
      </div>
    </>
  )
}

export default memo(EditorView)
