import { NumericInput } from '@blueprintjs/core'
import { notify } from '@inject/shared/notification/engine'
import { useLiveQuery } from 'dexie-react-hooks'
import { memo, useCallback, useEffect, useState, type FC } from 'react'
import ExpressionBuilder from '../ExpressionBuilder'
import useValidateExpression from '../ExpressionBuilder/useValidateExpression'
import SaveButtonGroup from '../SaveButtonGroup'
import TooltipLabel from '../Tooltips/TooltipLabel'
import { INJECT_CONNECTIONS_FORM } from '../assets/pageContent/injectSpecification'
import {
  addInjectControl,
  getInjectControlByInjectInfoId,
  updateInjectControl,
} from '../indexeddb/operations'
import type { InjectControl } from '../indexeddb/types'
import { InjectType } from '../indexeddb/types'

interface ConnectionsFormProps {
  injectInfoId: number
  injectType: InjectType
  changed: boolean
  onChangedChange: (value: boolean) => void
}

const ConnectionsForm: FC<ConnectionsFormProps> = ({
  injectInfoId,
  injectType,
  changed,
  onChangedChange,
}) => {
  const injectControl = useLiveQuery(
    () => getInjectControlByInjectInfoId(injectInfoId),
    [injectInfoId],
    null
  ) as InjectControl

  const [start, setStart] = useState<number>(0)
  const [delay, setDelay] = useState<number>(0)
  const [milestoneCondition, setMilestoneCondition] = useState<number[]>([])
  const { isValid } = useValidateExpression(milestoneCondition)

  useEffect(() => {
    setStart(injectControl?.start || 0)
    // eslint-disable-next-line @typescript-eslint/no-unused-expressions
    injectType === InjectType.QUESTIONNAIRE
      ? setDelay(0)
      : setDelay(injectControl?.delay || 0)
    setMilestoneCondition(injectControl?.milestoneCondition || [])
  }, [injectControl, injectType])

  const update = useCallback(
    async (newInjectControl: InjectControl | Omit<InjectControl, 'id'>) => {
      try {
        if (injectControl) {
          await updateInjectControl({
            id: injectControl.id,
            ...newInjectControl,
          })
        } else {
          await addInjectControl(newInjectControl)
        }
      } catch (error) {
        notify(
          `Failed to update inject control: ${error}`,
          JSON.stringify(error),
          {
            intent: 'danger',
          }
        )
      }
    },
    [injectControl]
  )

  const handleUpdate = useCallback(async () => {
    if (!changed) onChangedChange(true)
    await update({
      injectInfoId,
      start,
      delay,
      milestoneCondition: isValid ? milestoneCondition : [],
    })
    onChangedChange(false)
  }, [changed, injectInfoId, start, delay, milestoneCondition, isValid, update])

  useEffect(() => {
    if (changed) handleUpdate()
  }, [changed, handleUpdate])

  return (
    <div>
      <TooltipLabel label={INJECT_CONNECTIONS_FORM.time}>
        <NumericInput
          placeholder='Input number'
          min={0}
          value={start}
          onValueChange={(value: number) => setStart(value)}
        />
      </TooltipLabel>
      {injectType !== InjectType.QUESTIONNAIRE && (
        <TooltipLabel label={INJECT_CONNECTIONS_FORM.delay}>
          <NumericInput
            placeholder='Input number'
            min={0}
            value={delay}
            onValueChange={(value: number) => setDelay(value)}
          />
        </TooltipLabel>
      )}
      <ExpressionBuilder
        label={INJECT_CONNECTIONS_FORM.condition}
        initExpression={injectControl?.milestoneCondition}
        onExpressionChange={expression => setMilestoneCondition(expression)}
      />
      <SaveButtonGroup
        isValid={isValid}
        handleUpdate={() => handleUpdate()}
        prevPath='/editor/create/inject-specification'
      />
    </div>
  )
}

export default memo(ConnectionsForm)
