import React, { Fragment, useState } from 'react'
import Accordion from '@mui/material/Accordion/index.js'
import AccordionSummary from '@mui/material/AccordionSummary/index.js'
import AccordionDetails from '@mui/material/AccordionDetails/index.js'
import Checkbox from '@mui/material/Checkbox/index.js'
import FormControlLabel from '@mui/material/FormControlLabel/index.js'
import ExpandMoreIcon from '@mui/icons-material/ExpandMore.js'
import { array } from 'prop-types'

import FarmhandContext, { ContextData } from '../Farmhand/Farmhand.context.js'
import Item from '../Item/index.js'
import { itemsMap } from '../../data/maps.js'
import { sortItems } from '../../utils/sortItems.js'
import SearchBar from '../SearchBar/index.js'
import { Div } from '../Elements/index.js'

// Using Map for categories to preserve key order and enable Map methods
export const categoryIds = new Map([
  ['CROPS', 'CROPS'],
  ['SEEDS', 'SEEDS'],
  ['FORAGED_ITEMS', 'FORAGED_ITEMS'],
  ['FIELD_TOOLS', 'FIELD_TOOLS'],
  ['ANIMAL_PRODUCTS', 'ANIMAL_PRODUCTS'],
  ['ANIMAL_SUPPLIES', 'ANIMAL_SUPPLIES'],
  ['CRAFTED_ITEMS', 'CRAFTED_ITEMS'],
  ['MINED_RESOURCES', 'MINED_RESOURCES'],
])

const itemTypeCategoryMap = new Map([
  ['SEEDS', 'SEEDS'],
  ['COW_FEED', 'ANIMAL_SUPPLIES'],
  ['CRAFTED_ITEM', 'CRAFTED_ITEMS'],
  ['CROP', 'CROPS'],
  ['FERTILIZER', 'FIELD_TOOLS'],
  ['FUEL', 'MINED_RESOURCES'],
  ['HUGGING_MACHINE', 'ANIMAL_SUPPLIES'],
  ['MILK', 'ANIMAL_PRODUCTS'],
  ['ORE', 'MINED_RESOURCES'],
  ['SCARECROW', 'FIELD_TOOLS'],
  ['SPRINKLER', 'FIELD_TOOLS'],
  ['STONE', 'MINED_RESOURCES'],
  ['TREE', 'CROPS'],
  ['WEED', 'FORAGED_ITEMS'],
  ['WOOD', 'MINED_RESOURCES'],
])

// Initialize Map to group items into categories
const getItemCategories = () =>
  new Map(Array.from(categoryIds.keys()).map(key => [key, []]))

export const separateItemsIntoCategories = (items: farmhand.item[]) =>
  sortItems(items).reduce(
    (categories: Map<string, farmhand.item[]>, item: farmhand.item) => {
      const { type } = itemsMap[item.id]
      const category = itemTypeCategoryMap.get(type)

      if (category === 'CROPS') {
        const targetCategory =
          item.isPlantableCrop || item.isPlantableTree ? 'SEEDS' : 'CROPS'

        categories.get(targetCategory)?.push(item)
      } else if (category != null && categories.has(category)) {
        categories.get(category)?.push(item)
      }

      return categories
    },
    getItemCategories()
  )

const formatCategoryName = (key: string) =>
  key
    .replace(/_/g, ' ')
    .toLowerCase()
    .replace(/\b\w/g, (char: string) => char.toUpperCase())

export interface InventoryProps {
  items: farmhand.item[]
  title: string
  columns: number
  playerInventory?: ContextData['gameState']['playerInventory']
  shopInventory?: ContextData['gameState']['shopInventory']
  isPurchaseView?: boolean
  isSellView?: boolean
  itemCategories?: Map<string, farmhand.item[]>
  placeholder?: string
}

const Inventory = ({
  items,
  title,
  columns,
  playerInventory,
  shopInventory,
  isPurchaseView = false,
  isSellView = false,
  itemCategories = separateItemsIntoCategories(items),
  placeholder = 'Search inventory...',
}: InventoryProps) => {
  const [searchQuery, setSearchQuery] = useState('')
  const [selectedCategories, setSelectedCategories] = useState<string[]>([])
  const toggleCategory = (category: string) => {
    setSelectedCategories(prev =>
      prev.includes(category)
        ? prev.filter(c => c !== category)
        : [...prev, category]
    )
  }

  const filteredCategories = (Array.from(itemCategories.entries()) as [
    string,
    farmhand.item[]
  ][]).reduce(
    (
      filtered: Map<string, farmhand.item[]>,
      [category, categoryItems]: [string, farmhand.item[]]
    ) => {
      const matchingItems = categoryItems.filter(item => {
        const mappedItem = itemsMap[item.id]

        return (
          mappedItem &&
          mappedItem.name &&
          mappedItem.name.toLowerCase().includes(searchQuery.toLowerCase())
        )
      })

      if (
        matchingItems.length &&
        (!selectedCategories.length || selectedCategories.includes(category))
      ) {
        filtered.set(category, matchingItems)
      }
      return filtered
    },
    new Map()
  )

  return (
    <Div className="Inventory">
      <SearchBar placeholder={placeholder} onSearch={setSearchQuery} />
      {!isPurchaseView && (
        <Accordion>
          <AccordionSummary
            expandIcon={<ExpandMoreIcon />}
            aria-controls="filter-content"
            id="filter-header"
          >
            <h4>Filter by category</h4>
          </AccordionSummary>
          <AccordionDetails>
            <Div
              className="filter-section"
              sx={{
                marginBottom: '20px',
                padding: '10px',
                border: '1px solid #ccc',
                borderRadius: '5px',
                backgroundColor: '#f7f7f7',
                '& h4': {
                  marginBottom: '10px',
                  fontSize: '16px',
                  color: '#555',
                },
              }}
            >
              {Array.from(categoryIds.keys()).map(key => (
                <FormControlLabel
                  key={key}
                  sx={{
                    display: 'block',
                  }}
                  control={
                    <Checkbox
                      disabled={isPurchaseView}
                      checked={selectedCategories.includes(key)}
                      onChange={() => toggleCategory(key)}
                    />
                  }
                  label={formatCategoryName(key)}
                />
              ))}
            </Div>
          </AccordionDetails>
        </Accordion>
      )}
      {Array.from(
        (filteredCategories as Map<string, farmhand.item[]>).entries()
      ).map(([category, categoryItems]: [string, farmhand.item[]]) =>
        categoryItems.length ? (
          <Fragment key={category}>
            <section>
              <h3>{formatCategoryName(category)}</h3>
              <ul className="card-list">
                {categoryItems.map(item => (
                  <li key={item.id}>
                    <Item
                      {...{
                        isPurchaseView,
                        isSellView,
                        item,
                        showQuantity: isPurchaseView,
                      }}
                    />
                  </li>
                ))}
              </ul>
            </section>
          </Fragment>
        ) : null
      )}
    </Div>
  )
}

Inventory.propTypes = {
  items: array.isRequired,
  playerInventory: array,
  shopInventory: array,
}

export default function Consumer(
  props: Partial<Parameters<typeof Inventory>[0]>
) {
  return (
    <FarmhandContext.Consumer>
      {({ gameState, handlers }) => (
        <Inventory
          {...({
            ...gameState,
            ...handlers,
            ...props,
          } as Parameters<typeof Inventory>[0])}
        />
      )}
    </FarmhandContext.Consumer>
  )
}
