import { normalize, schema } from 'normalizr'

import { Menu as ApiMenu, System as ApiSystem } from '@agiliza/api/interfaces/System'
import { Menu, MI, MS, MU, SystemData, SystemEntities } from '@agiliza/redux/entities/system'
import { Operations } from '@dynamo/utils'

let currentId = 0

function mapOpApiToStore(operation: string): Operations {
  switch (operation) {
    case '1':
      return 'create'
    case '2':
      return 'read'
    case '3':
      return 'update'
    case '4':
      return 'delete'
    default:
      return 'unknown'
  }
}

function mapMenuApiToStore(menus: ApiMenu[]): Menu[] {
  if (!menus) return []
  const menuTree = menus.map((m) => {
    if (m._Type === 'MI') {
      return {
        id: (++currentId).toString(),
        name: m._Name,
        type: 'MI',
        submenus: mapMenuApiToStore(m.Submenus),
      } as MI
    } else if (m._Type === 'MS') {
      return {
        id: (++currentId).toString(),
        name: m._Name,
        entity: m._EN,
        type: 'MS',
        actions: mapMenuApiToStore(m.Actions),
      } as MS
    } else {
      return {
        id: (++currentId).toString(),
        name: m._Name,
        operation: mapOpApiToStore(m._OP),
        type: 'MU',
        useCase: m._UC,
        view: m._VIEW,
      } as MU
    }
  })
  return menuTree
}

const muSchema = new schema.Entity('MU')
const msSchema = new schema.Entity('MS', { actions: [muSchema] })

const mapMenusToEntities = (menus: Menu[]) => {
  const entities: SystemEntities = menus.reduce(
    (acc, menu) => {
      if (menu.type === 'MI') {
        const ents = mapMenusToEntities(menu.submenus)
        acc.MS = { ...acc.MS, ...ents.MS }
        acc.MU = { ...acc.MU, ...ents.MU }
        return acc
      } else if (menu.type === 'MS') {
        const { entities: ents }: { entities: SystemEntities } = normalize(menu, msSchema)
        acc.MS = { ...acc.MS, ...ents.MS }
        acc.MU = { ...acc.MU, ...ents.MU }
        return acc
      } else {
        acc.MU[menu.id] = menu
        return acc
      }
    },
    { MS: {}, MU: {} } as SystemEntities
  )
  return entities
}

export function mapSystemApiToStore(system?: ApiSystem): SystemData {
  if (!system) return {}
  const menus = mapMenuApiToStore(system.Menus)

  const entities = mapMenusToEntities(menus)

  currentId = 0

  return {
    system: {
      name: system._Name,
      menus,
    },
    entities,
  }
}
