import { Button, Layout } from 'antd'
import {
  AuditOutlined,
  CheckOutlined,
  CloseOutlined,
  FileWordOutlined,
  LoadingOutlined,
  ReloadOutlined,
  WarningOutlined,
} from '@ant-design/icons'
import { memo, useCallback, useEffect, useMemo, useState } from 'react'

import { useIdWell } from '@asb/context'
import LoaderPortal from '@components/LoaderPortal'
import { downloadFile, formatBytes, invokeWebApiWrapperAsync } from '@components/factory'
import { arrayOrDefault, formatDate, wrapPrivateComponent } from '@utils'
import { DrillingProgramService } from '@api'

import CategoryAdder from './CategoryAdder'
import CategoryRender from './CategoryRender'
import CategoryEditor from './CategoryEditor'
import CategoryHistory from './CategoryHistory'

import '@styles/drilling_program.less'

const ID_STATE = {
  NotInitialized: 0,
  Approving: 1,
  Creating: 2,
  Ready: 3,
  Error: 4,
  Unknown: -1,
}

const STATE_STRING = {
  [ID_STATE.NotInitialized]: { icon: CloseOutlined, text: 'Не настроена' },
  [ID_STATE.Approving]: { icon: AuditOutlined, text: 'Согласовывается' },
  [ID_STATE.Creating]: { icon: LoadingOutlined, text: 'Формируется' },
  [ID_STATE.Ready]: { icon: CheckOutlined, text: 'Сформирована' },
  [ID_STATE.Error]: { icon: WarningOutlined, text: 'Ошибка формирования' },
  [ID_STATE.Unknown]: { icon: WarningOutlined, text: 'Неизвестно' },
}

const DrillingProgram = memo(() => {
  const [selectedCategory, setSelectedCategory] = useState()
  const [historyVisible, setHistoryVisible] = useState(false)
  const [editorVisible, setEditorVisible] = useState(false)
  const [showLoader, setShowLoader] = useState(false)
  const [categories, setCategories] = useState([])
  const [data, setData] = useState({})

  const idWell = useIdWell()

  const {
    idState,
    permissionToEdit,
    parts,
    program,
    error,
  } = useMemo(() => data, [data])

  const stateId = useMemo(() => idState ?? ID_STATE.Unknown, [idState])
  const state = useMemo(() => STATE_STRING[stateId], [stateId])
  const StateIcon = useMemo(() => state.icon, [state?.icon])

  const updateData = useCallback(async () => await invokeWebApiWrapperAsync(
    async () => {
      const data = await DrillingProgramService.getState(idWell)
      const categories = arrayOrDefault(await DrillingProgramService.getCategories(idWell))
      setData(data)
      setCategories(categories.filter(cat => {
        if (cat?.id && (cat.name || cat.shortName))
          if (data.parts?.findIndex((val) => val.idFileCategory === cat.id) < 0)
            return true
        return false
      }))
    },
    setShowLoader,
    `Не удалось загрузить название скважины "${idWell}"`
  ), [idWell])

  useEffect(() => {
    updateData()
  }, [updateData])

  const onCategoryEdit = useCallback((catId) => {
    setSelectedCategory(catId)
    setEditorVisible(!!catId)
  }, [])

  const onCategoryHistory = useCallback((catId) => {
    setSelectedCategory(catId)
    setHistoryVisible(!!catId)
  }, [])

  const onEditorClosed = useCallback((needUpdate) => {
    setEditorVisible(false)
    if (needUpdate)
      updateData()
  }, [updateData])

  const clearError = useCallback(() => invokeWebApiWrapperAsync(
    async () => {
      await DrillingProgramService.clearError(idWell)
      await updateData()
    },
    setShowLoader,
    `Не удалось сбросить ошибку формирования программы бурения для скважины ${idWell}`
  ), [idWell])

  return (
    <LoaderPortal show={showLoader}>
      <Layout style={{ backgroundColor: 'white' }}>
        <div className={'drilling_program'}>
          <div className={'program_header'}>
            <h3>Программа бурения</h3>
            {permissionToEdit && (
              <div>
                <CategoryAdder categories={categories} onUpdate={updateData} />
              </div>
            )}
          </div>
          <div className={'program_content'}>
            {stateId === ID_STATE.Ready ? (
              <>
                <Button
                  type={'link'}
                  icon={<FileWordOutlined />}
                  style={{ marginLeft: '10px' }}
                  onClick={() => downloadFile(program)}
                >
                  {program?.name}
                </Button>
                <div className={'m-10'}>Размер: {formatBytes(program?.size)}</div>
                <div className={'m-10'}>Сформирован: {formatDate(program?.uploadDate)}</div>
              </>
            ) : stateId === ID_STATE.Error ? (
              <>
                <h3 className={'program_status error'}>
                  <StateIcon className={'m-10'} />
                  {error?.message ?? state.text}
                </h3>
                <Button onClick={clearError} icon={<ReloadOutlined />}>
                  Сбросить статус ошибки
                </Button>
              </>
            ) : (
              <h3 className={'program_status'}>
                <StateIcon className={'m-10'} />
                {state.text}
              </h3>
            )}
          </div>
        </div>

        {parts?.map?.((part, idx) => part && (
          <CategoryRender
            key={`${idx}`}
            partData={part}
            onEdit={permissionToEdit && onCategoryEdit}
            onUpdate={updateData}
            onHistory={onCategoryHistory}
          />
        ))}

        {permissionToEdit && (
          <>
            <CategoryEditor
              visible={editorVisible}
              onClosed={onEditorClosed}
              category={parts?.find((part) => part.idFileCategory === selectedCategory) ?? {}}
            />
          </>
        )}

        <CategoryHistory
          idCategory={selectedCategory}
          onClose={() => setHistoryVisible(false)}
          visible={historyVisible}
        />
      </Layout>
    </LoaderPortal>
  )
})

export default wrapPrivateComponent(DrillingProgram, {
  requirements: [ 'DrillingProgram.get' ],
  title: 'Программа бурения',
  route: 'drillingProgram',
})
