import { FC, useMemo, useRef, useState } from 'react'
import { GroupBox } from './GroupBox/GroupBox'
import styles from './Home.module.css'
import { useFactories } from '../../src/hooks/useFactories'
import { EnrichedEntity } from '../../src/types'
import { EntitySpan } from './EntitySpan/EntitySpan'
import { postFetchJson, useGroups } from '../contexts/GroupProvider'
import { Preferences } from './Preferences/Preferences'
import { download, streamToArrayBuffer } from '../../src/download'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { UploadDataBody } from '../../src/types/ApiSchemasFrontend'

export const Home: FC = () => {
  const router = useRouter()
  const { factories } = useFactories()
  const {
    groups,
    addGroup,
    doNotSuggest,
    baseFactories,
    ignoredFactories,
    setIgnoredFactories,
    store,
    load
  } = useGroups()
  const [newGroupValue, setNewGroupValue] = useState('New group')
  const inputRef = useRef<HTMLInputElement>(null)

  const [missingExport, missingMall] = useMemo<[EnrichedEntity[], EnrichedEntity[]]>(() => {
    return factories
      .filter(factory => !doNotSuggest.has(factory.href) && factory.recipe)
      .reduce(
        (acc, factory) =>
          (factory.usedBy?.length ?? 0) >= 3
            ? [[...acc[0], factory], acc[1]]
            : [acc[0], [...acc[1], factory]],
        [[], []] as [EnrichedEntity[], EnrichedEntity[]]
      )
  }, [factories, doNotSuggest])

  return (
    <main>
      <h1>Factorio Microservices</h1>
      <button
        onClick={() => {
          download('factorio-microservices.bin', store())
        }}
      >
        Store
      </button>
      <button
        onClick={() =>
          postFetchJson(router, `/api/${router.query.id}/upload`, {
            groups,
            ignored: ignoredFactories,
            base: baseFactories
          } as UploadDataBody)
        }
      >
        Upload
      </button>
      <input
        type={'file'}
        multiple={false}
        ref={inputRef}
        onChange={async evt => {
          const stream = evt.currentTarget.files?.[0].stream() as
            | globalThis.ReadableStream<Uint8Array>
            | undefined
          if (stream) {
            const array = await streamToArrayBuffer(stream)
            load(array)
            if (inputRef.current) inputRef.current.value = null as unknown as string
          }
        }}
      />
      <Link href={{ pathname: '/visualize', query: router.query }}>Visualize</Link>
      <Preferences />
      <fieldset>
        <legend>Missing export factories</legend>
        <div className={styles.missingFactories}>
          {missingExport.map(missing => (
            <EntitySpan
              key={missing.href}
              value={missing}
              onClick={() => {
                addGroup(newGroupValue !== 'New group' ? newGroupValue : missing.name, [
                  missing.href
                ])
                setNewGroupValue('New group')
              }}
              onContextMenu={event => {
                event.preventDefault()
                setIgnoredFactories([...ignoredFactories, missing.href])
              }}
              leftClickText={'Create a new group with this name and item as exported factory'}
              rightClickText={'Exclude this recipe from suggestions'}
            />
          ))}
        </div>
      </fieldset>
      <fieldset>
        <legend>Missing mall factories</legend>
        <div className={styles.missingFactories}>
          {missingMall.map(missing => (
            <EntitySpan
              key={missing.href}
              value={missing}
              onClick={() => {
                addGroup(
                  newGroupValue !== 'New group' ? newGroupValue : missing.name,
                  [],
                  [missing.href]
                )
                setNewGroupValue('New group')
              }}
              onContextMenu={event => {
                event.preventDefault()
                setIgnoredFactories([...ignoredFactories, missing.href])
              }}
              leftClickText={'Create a new group with this name and item as mall factory'}
              rightClickText={'Exclude this recipe from suggestions'}
            />
          ))}
        </div>
      </fieldset>
      <div className={styles.grid}>
        {Object.values(groups)
          .sort((a, b) => a.name.localeCompare(b.name))
          .map(group => (
            <GroupBox key={group.name} group={group} />
          ))}
      </div>
    </main>
  )
}
