import { stageFocusType, toolLevel, toolType } from '../enums.js'
import { STANDARD_VIEW_LIST } from '../constants.js'

import { farmProductsSold } from './farmProductsSold.js'
import { getLevelEntitlements } from './getLevelEntitlements.js'
import { levelAchieved } from './levelAchieved.js'

export const transformStateDataForImport = (
  state: farmhand.state
): farmhand.state => {
  let sanitizedState: Record<string, unknown> = { ...state }

  const rejectedKeys = ['version']

  rejectedKeys.forEach(rejectedKey => delete sanitizedState[rejectedKey])

  if (sanitizedState.experience === 0) {
    sanitizedState.experience = farmProductsSold(sanitizedState.itemsSold || {})
  }

  if (
    sanitizedState.showHomeScreen === false &&
    sanitizedState.stageFocus === stageFocusType.HOME
  ) {
    sanitizedState = {
      ...sanitizedState,
      stageFocus: STANDARD_VIEW_LIST[0] as farmhand.stageFocusType,
    }
  }

  // NOTE: This is a mitigation for
  // https://github.com/jeremyckahn/farmhand/issues/546. There's no expected
  // scenario where a cow would be present in cowBreedingPen but not
  // cowInventory, but at least one player's game somehow got into that state.
  // This block detects such an invalid state and corrects it.
  {
    // TODO: Add defensive check safeguards for sanitizedState.cowBreedingPen
    // and sanitizedState.cowInventory to prevent TypeError crashes during
    // corrupt/legacy state imports.
    const {
      cowId1,
      cowId2,
    } = sanitizedState.cowBreedingPen as farmhand.state['cowBreedingPen']

    const cowPenIdMap = (sanitizedState.cowInventory as farmhand.cow[]).reduce(
      (acc: Record<string, farmhand.cow>, cow: farmhand.cow) => {
        acc[cow.id] = cow

        return acc
      },
      {}
    )

    const isCowInBreedingPenMissingFromInventory = [cowId1, cowId2].some(
      cowId => {
        return cowId && !(cowId in cowPenIdMap)
      }
    )

    if (isCowInBreedingPenMissingFromInventory) {
      // Resets cowBreedingPen state
      sanitizedState.cowBreedingPen = {
        cowId1: null,
        cowId2: null,
        daysUntilBirth: -1,
      }
    }
  }

  // NOTE: Legacy data trasformation for https://github.com/jeremyckahn/farmhand/issues/387
  if (sanitizedState.id) {
    sanitizedState.playerId = sanitizedState.id
    delete sanitizedState.id
  }

  // NOTE: Legacy data transformation for saves persisted before the AXE
  // tool was added. toolLevels is merged as a whole object on import (see
  // useFarmhand.ts), so an old save's toolLevels has no AXE key at all
  // rather than an explicit UNAVAILABLE - leaving Toolbelt.tsx unable to
  // resolve a tool image for it and crashing on tool.level.toLowerCase().
  //
  // A save whose player is already past the level that unlocks the axe
  // (see levels.ts) never gets another chance to unlock it retroactively -
  // processLevelUp only fires on a *new* level-up crossing that threshold,
  // not on load - so backfill straight to DEFAULT for those players rather
  // than leaving them permanently locked out of a tool they should already
  // have.
  if (
    sanitizedState.toolLevels &&
    !(sanitizedState.toolLevels as farmhand.state['toolLevels'])[toolType.AXE]
  ) {
    const hasUnlockedAxe = Boolean(
      getLevelEntitlements(
        levelAchieved((sanitizedState.experience ?? 0) as number)
      ).tools[toolType.AXE]
    )

    sanitizedState.toolLevels = {
      ...(sanitizedState.toolLevels as farmhand.state['toolLevels']),
      [toolType.AXE]: hasUnlockedAxe
        ? toolLevel.DEFAULT
        : toolLevel.UNAVAILABLE,
    }
  }

  return (sanitizedState as unknown) as farmhand.state
}
