import {
  cropLifeStage,
  fertilizerType,
  itemType,
  toolLevel,
  toolType,
} from '../../enums.js'
import { itemsMap } from '../../data/maps.js'
import { doesInventorySpaceRemain } from '../../utils/doesInventorySpaceRemain.js'
import { getCropLifeStage } from '../../utils/getCropLifeStage.js'
import { getPlotContentType } from '../../utils/getPlotContentType.js'
import { getSeedItemIdFromFinalStageCropItemId } from '../../utils/getSeedItemIdFromFinalStageCropItemId.js'
import { getInventoryQuantityMap } from '../../utils/getInventoryQuantityMap.js'

import { addItemToInventory } from './addItemToInventory.js'
import { modifyFieldPlotAt } from './modifyFieldPlotAt.js'
import { removeFieldPlotAt } from './removeFieldPlotAt.js'
import { plantInPlot } from './plantInPlot.js'

const { GROWN } = cropLifeStage

function getHarvestedQuantity(state: farmhand.state): number {
  let amount = 1

  switch (state.toolLevels[toolType.SCYTHE]) {
    case toolLevel.BRONZE:
      amount += 1
      break

    case toolLevel.IRON:
      amount += 2
      break

    case toolLevel.SILVER:
      amount += 3
      break

    case toolLevel.GOLD:
      amount += 4
      break

    default:
      amount = 1
  }

  return amount
}

function harvestCrops(
  state: farmhand.state,
  x: number,
  y: number
): farmhand.state {
  const row = state.field[y]
  const crop = row[x]

  if (!crop) return state

  const item = itemsMap[crop.itemId]

  if (!item) return state

  const seedItemIdForCrop = getSeedItemIdFromFinalStageCropItemId(item.id)
  const plotWasRainbowFertilized =
    crop.fertilizerType === fertilizerType.RAINBOW

  const harvestedQuantity = getHarvestedQuantity(state)

  state = removeFieldPlotAt(state, x, y)
  state = addItemToInventory(state, item, harvestedQuantity)

  const { cropType } = item

  if (!cropType) return state

  if (plotWasRainbowFertilized) {
    const seedsForHarvestedCropAreAvailable =
      getInventoryQuantityMap(state.inventory)[seedItemIdForCrop] > 0

    if (seedsForHarvestedCropAreAvailable) {
      state = plantInPlot(state, x, y, seedItemIdForCrop)
      state = modifyFieldPlotAt(state, x, y, updatedCrop => {
        if (!updatedCrop) {
          return updatedCrop
        }

        return {
          ...updatedCrop,
          fertilizerType: fertilizerType.RAINBOW,
        }
      })
    }
  }

  const { cropsHarvested } = state

  return {
    ...state,
    cropsHarvested: {
      ...cropsHarvested,
      [cropType]: (cropsHarvested[cropType] || 0) + harvestedQuantity,
    },
  }
}

function harvestWeed(
  state: farmhand.state,
  x: number,
  y: number
): farmhand.state {
  const row = state.field[y]
  const crop = row[x]

  if (!crop) return state

  const item = itemsMap[crop.itemId]
  const harvestedQuantity = getHarvestedQuantity(state)

  state = removeFieldPlotAt(state, x, y)
  state = addItemToInventory(state, item, harvestedQuantity)

  return state
}

export const harvestPlot = (
  state: farmhand.state,
  x: number,
  y: number
): farmhand.state => {
  const row = state.field[y]
  const crop = row[x]

  if (!crop) return state
  if (!doesInventorySpaceRemain(state)) return state

  if (
    getPlotContentType(crop) === itemType.CROP &&
    getCropLifeStage(crop) === GROWN
  ) {
    return harvestCrops(state, x, y)
  } else if (getPlotContentType(crop) === itemType.WEED) {
    return harvestWeed(state, x, y)
  }

  return state
}
