import {FC, memo, useCallback, useEffect, useMemo} from "react";
import {FactorySelect} from "../FactorySelect/FactorySelect";
import {useFactories} from "../../../src/hooks/useFactories";
import {Entity, Group} from "../../../src/types";
import styles from "./Group.module.css"
import {EntitySpan} from "../EntitySpan/EntitySpan";
import {useGroups} from "../../contexts/GroupProvider";

interface Props {
  group: Group
}

const GroupBoxBase: FC<Props> = ({ group }) => {
  const {factories} = useFactories()
  console.log("group")
  const {
    doNotSuggest,
    setFactories,
    ignoredFactories,
    setIgnoredFactories,
    renameGroup,
    removeGroup,
    getInputType
  } = useGroups()
  const {
    name,
    inputs,
    intermediates,
    exports,
    malls
  } = group

  const calculatedInputs = useMemo<string[]>(() => {
    const allProducingFactories = [...intermediates, ...exports, ...malls]
    const newData: string[] = factories
      .filter(factory => allProducingFactories.includes(factory.href))
      .flatMap(factory => Object.keys(factory.recipe?.prerequisites ?? {}))
    const uniqueInputs = Array.from(new Set(newData))
    return uniqueInputs
      .filter(input => !allProducingFactories.includes(input))
      .sort((a, b) => a.localeCompare(b))
  }, [factories, intermediates, exports, malls])

  const suggestions = useMemo<Entity[]>(() => {
    const selectedValues = Array.from(new Set([...inputs, ...intermediates, ...exports, ...malls]))
    const availableIngredients = Array.from(new Set([...selectedValues, ...calculatedInputs]))
    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))
      })
  }, [doNotSuggest, factories, calculatedInputs, inputs, intermediates, exports, malls])

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

  const setInputFactories = useCallback((factories: string[]) => setFactories(name, factories, 'inputs'), [setFactories, name])
  const setIntermediateFactories = useCallback((factories: string[]) => setFactories(name, factories, 'intermediates'), [setFactories, name])
  const setExportFactories = useCallback((factories: string[]) => setFactories(name, factories, 'exports'), [setFactories, name])
  const setMallFactories = useCallback((factories: string[]) => setFactories(name, factories, 'malls'), [setFactories, name])

  return <div className={styles.root}>
    <h3
      contentEditable={true}
      suppressContentEditableWarning={true}
      onBlur={event => {
        event.currentTarget.innerText = event.currentTarget.innerText.trim()
        renameGroup(name, event.currentTarget.innerText);
      }}
    >
      {name}
    </h3>
    <button className={styles.quit} onClick={() => removeGroup(name)} style={{display: 'block'}}>X</button>
    <label>Additional Inputs</label>
    <FactorySelect
      id={name+"-inputs"}
      factories={inputs}
      onSetFactories={setInputFactories}
    />
    <label>Intermediate Factories</label>
    <FactorySelect
      id={name+"-intermediates"}
      factories={intermediates}
      onSetFactories={setIntermediateFactories}
    />
    <label>Exported Factories</label>
    <FactorySelect
      id={name+"-exports"}
      factories={exports}
      onSetFactories={setExportFactories}
    />
    <label>Mall Factories</label>
    <FactorySelect
      id={name+"-malls"}
      factories={malls}
      onSetFactories={setMallFactories}
    />
      <h4>Inputs</h4>
      <div className={styles.flex}>
        { calculatedInputs.map(input => <EntitySpan
          key={input}
          value={input}
          onClick={() => addFactory(input, 'intermediates')}
          state={getInputType(input)}
          leftClickText={"Add to intermediate factories"}
        />) }
    </div>
    { suggestions.length ? <>
      <h4>Suggestions</h4>
      <div className={styles.flex}>
        { suggestions.map(suggestion => <EntitySpan
          key={suggestion.href}
          value={suggestion}
          onClick={() => addFactory(suggestion.href, 'exports')}
          onContextMenu={event => {
            event.preventDefault()
            setIgnoredFactories([...ignoredFactories, suggestion.href])
          }}
          leftClickText={"Add to exported factories"}
          rightClickText={"Exclude this recipe from suggestions"}
        />) }
      </div>
    </> : null }
  </div>
}

export const GroupBox = memo(GroupBoxBase)
