import { FC, memo, useCallback, useMemo, useState } from 'react'
import { FactorySelect } from '../FactorySelect/FactorySelect'
import { EnrichedEntity, Group } from '../../../src/types'
import styles from './GroupBox.module.css'
import { EntitySpan } from '../EntitySpan/EntitySpan'
import { useGroups } from '../../contexts/GroupProvider'
import { calculateInputs } from '../../../src/calculateInputs'
import { uniquify } from '../../../src/utils'
import { useFactories } from '../../contexts/FactoryProvider'
import { i18n, I18n } from '../../shared/I18n/I18n'
import { useIntl } from 'react-intl'
import { ButtonVisualize } from '../../shared/ButtonVisualize/ButtonVisualize'
import { Heading } from '../../shared/Heading'
import typography from '../../../styles/typography.module.css'
import cx from 'classnames'

interface Props {
  group: Group
}

const GroupBoxBase: FC<Props> = ({ group }) => {
  const intl = useIntl()
  const { factories, findFactory } = useFactories()
  const {
    doNotSuggest,
    setFactories,
    baseFactories,
    exportedFactories,
    ignoredFactories,
    setIgnoredFactories,
    renameGroup,
    removeGroup,
    getInputType
  } = useGroups()
  const { name, exports, malls } = group
  const nameForId = useMemo(() => name.replace(/[^a-z\d_-]/gi, ''), [name])

  const [isDeleteConfirm, setDeleteConfirm] = useState(false)

  const [inputs, intermediates] = useMemo(() => {
    const allProducingFactories = [...exports, ...malls]
    return calculateInputs(allProducingFactories, baseFactories, exportedFactories, findFactory)
  }, [exports, malls, baseFactories, findFactory, exportedFactories])

  const [suggestionsExport, suggestionMall] = useMemo<[EnrichedEntity[], EnrichedEntity[]]>(() => {
    const selectedValues = uniquify([...exports, ...malls])
    const availableIngredients = uniquify([...selectedValues, ...intermediates, ...inputs])
    return factories
      .filter(factory => {
        if (!factory.recipe) return false
        if (selectedValues.includes(factory.href)) return false
        if (doNotSuggest.has(factory.href)) return false
        const prerequisites = Object.keys(factory.recipe.prerequisites ?? {})
        return prerequisites.every(pre => availableIngredients.includes(pre))
      })
      .reduce(
        (acc, factory) =>
          (factory.usedBy?.length ?? 0) >= 3
            ? [[...acc[0], factory], acc[1]]
            : [acc[0], [...acc[1], factory]],
        [[], []] as [EnrichedEntity[], EnrichedEntity[]]
      )
  }, [exports, malls, intermediates, inputs, factories, doNotSuggest])

  const addFactory = useCallback(
    (uid: string, type: Parameters<typeof setFactories>[2]) => {
      setFactories(name, [...group[type], uid], type)
    },
    [group, name, setFactories]
  )

  const setExportFactories = useCallback(
    (exportFactories: string[]) => setFactories(name, exportFactories, 'exports'),
    [setFactories, name]
  )
  const setMallFactories = useCallback(
    (mallFactories: string[]) => setFactories(name, mallFactories, 'malls'),
    [setFactories, name]
  )

  return (
    <div className={styles.root}>
      <ButtonVisualize groupId={group.name} />
      <Heading
        type={'subsection'}
        className={styles.heading}
        contentEditable={true}
        suppressContentEditableWarning={true}
        onBlur={event => {
          event.currentTarget.innerText = event.currentTarget.innerText.trim()
          renameGroup(name, event.currentTarget.innerText)
        }}
        onKeyDown={event => {
          if (event.key === 'Enter') {
            event.preventDefault()
            event.currentTarget.blur()
          }
          if (event.key === 'Escape') {
            event.preventDefault()
            event.currentTarget.innerText = name
            event.currentTarget.blur()
          }
        }}
      >
        {name}
      </Heading>
      <button
        className={styles.quit}
        onBlur={() => setDeleteConfirm(false)}
        onClick={() => (!isDeleteConfirm ? setDeleteConfirm(true) : removeGroup(name))}
        style={{ display: 'block' }}
      >
        {isDeleteConfirm ? i18n(intl, 'page.home.group.delete.confirmation') : 'X'}
      </button>
      <label htmlFor={nameForId + '-exports'} className={styles.label}>
        <span className={typography.titleMedium}>
          <I18n id={'page.home.group.item.export'} />
        </span>
        <FactorySelect
          id={nameForId + '-exports'}
          factories={exports}
          onSetFactories={setExportFactories}
        />
      </label>
      <label htmlFor={nameForId + '-exports'} className={cx(styles.label, styles.marginTop)}>
        <span className={typography.titleMedium}>
          <I18n id={'page.home.group.item.mall'} />
        </span>
        <FactorySelect
          id={nameForId + '-malls'}
          factories={malls}
          onSetFactories={setMallFactories}
        />
      </label>
      {inputs.length ? (
        <>
          <span className={cx(typography.titleMedium, styles.marginTop)}>
            <I18n id={'page.home.group.item.input'} values={{ amount: inputs.length }} />
          </span>
          <div className={styles.flex}>
            {inputs.map(input => (
              <EntitySpan
                key={input}
                value={input}
                state={getInputType(input)}
                onContextMenu={event => {
                  event.preventDefault()
                  setIgnoredFactories([...ignoredFactories, input])
                }}
                rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
              />
            ))}
          </div>
        </>
      ) : null}
      {intermediates.length ? (
        <>
          <span className={cx(typography.titleMedium, styles.marginTop)}>
            <I18n
              id={'page.home.group.item.intermediate'}
              values={{ amount: intermediates.length }}
            />
          </span>
          <div className={styles.flex}>
            {intermediates.map(intermediate => (
              <EntitySpan
                key={intermediate}
                value={intermediate}
                state={getInputType(intermediate)}
              />
            ))}
          </div>
        </>
      ) : null}
      {suggestionsExport.length ? (
        <>
          <span className={cx(typography.titleMedium, styles.marginTop)}>
            <I18n id={'page.home.group.item.suggestion.export'} />
          </span>
          <div className={styles.flex}>
            {suggestionsExport.map(suggestion => (
              <EntitySpan
                key={suggestion.href}
                value={suggestion}
                onClick={() => addFactory(suggestion.href, 'exports')}
                onContextMenu={event => {
                  event.preventDefault()
                  setIgnoredFactories([...ignoredFactories, suggestion.href])
                }}
                leftClickText={i18n(intl, 'page.home.tooltip.action.add_to_export')}
                rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
              />
            ))}
          </div>
        </>
      ) : null}
      {suggestionMall.length ? (
        <>
          <span className={cx(typography.titleMedium, styles.marginTop)}>
            <I18n id={'page.home.group.item.suggestion.mall'} />
          </span>
          <div className={styles.flex}>
            {suggestionMall.map(suggestion => (
              <EntitySpan
                key={suggestion.href}
                value={suggestion}
                onClick={() => addFactory(suggestion.href, 'malls')}
                onContextMenu={event => {
                  event.preventDefault()
                  setIgnoredFactories([...ignoredFactories, suggestion.href])
                }}
                leftClickText={i18n(intl, 'page.home.tooltip.action.add_to_mall')}
                rightClickText={i18n(intl, 'page.home.tooltip.action.exclude_suggestion')}
              />
            ))}
          </div>
        </>
      ) : null}
    </div>
  )
}

export const GroupBox = memo(GroupBoxBase)
