import React, { useMemo } from 'react'
import { Box, Text } from '@native-base/formik-ui'
import { observer } from 'mobx-react-lite'
import { useAppStore } from './store'
import { FormScreen } from './FormScreen'
import type { NativeStackScreenProps } from '@react-navigation/native-stack'
import { createEntityTable, EntityTableProps, useLoadedItem } from './EntityTable'
import { Button, Center, Heading, HStack, VStack } from 'native-base'
import SeparatorLine from './SeparatorLine'
import { AssocSelectionType, EntityModelType, isRelation, QueryState, RelationModelType } from './EntityModel'
import { MaterialIcons } from '@expo/vector-icons'
import { useFocusEffect } from '@react-navigation/native'

type Props = NativeStackScreenProps<any, any>

const EntityDetailsScreen: React.FC<Props> = observer((props) => {
  const appStore = useAppStore()
  const params = appStore.getRouteConfig(props.route)
  // The entity we display the details of. We display its own data and all related data in tables.
  const rootEntityModel = params.rootEntityModel as EntityModelType
  const { loadingOpacity } = useLoadedItem(rootEntityModel)
  //const rootName = getType(rootEntityModel).name;
  const MyData = rootEntityModel.config.dataComponentVal()

  // setOnDeletePress accepts either an explicit tablesAndModels value (when called from the tablesAndModels preparation useEffect) or takes
  // it from the tablesAndModels state (when called by useFocusEffect)
  const setOnDeletePress = (tablesAndModels) => {
    tablesAndModels.forEach((tableAndModel) => {
      const relatedModel = tableAndModel.model as any
      // Only for non m2m related fields:
      if (!isRelation(relatedModel)) {
        relatedModel.config.entityListScreenConfig.onDeletePress = (_event, item, _config) => {
          relatedModel.delete([item])
          relatedModel.reloadList()
        }
      }
    })
  }

  // Rebuild only when loadedItem changes
  const tablesAndModels = useMemo(() => {
    const res = Object.keys(rootEntityModel.relations).map((key) => {
      const m = rootEntityModel.relations[key]
      let relation: RelationModelType = m as RelationModelType
      let fieldModel: EntityModelType = relation.fieldModel

      fieldModel.configureRelated(rootEntityModel, params)
      let defaultProps: EntityTableProps<any> = {
        model: fieldModel,
        fieldName: key,
        relation: relation,
      }

      // If no asssociation selection, we can still create new associated entities
      if (relation.assocSelectionType == AssocSelectionType.NONE) {
        fieldModel.config.entityListScreenConfig!.onSelection = (_event, item: any) => {
          fieldModel.setEditId(item.id)
          appStore.navigate(props.navigation as any, fieldModel.config.editFormScreenRouteNameVal(), {
            parentRoute: props.route.name,
            entityModel: fieldModel, // an item of the related entity selected by clicking on table row
            rootEntityModel: rootEntityModel, // main entity we display the details of
            // Use explicit title with the selected item
            title: fieldModel.config.editFormScreenRouteTitleVal(item),
          })
        }

        if (relation.allowCreatingNewRelated || relation.prepareNew || relation.createNew) {
          fieldModel.config.entityListScreenConfig!.onNewPress = (_event) => {
            fieldModel.setEditId(null)
            appStore.navigate(props.navigation as any, fieldModel.config.createFormScreenRouteNameVal(), {
              parentRoute: props.route.name,
              entityModel: fieldModel,
              rootEntityModel: rootEntityModel,
              relation: relation,
              title: fieldModel.config.createFormScreenRouteTitleVal(),
            })
          }
        }

        if (relation.unassociate) {
          fieldModel.config.entityListScreenConfig!.onUnassocPress = (_e, item: any, _config) => {
            const mut = rootEntityModel.unassociate(relation, [item.id])
            mut.then(
              (/*result: any*/) => {
                fieldModel.reloadList()
              },
              (/*error: any*/) => {}
            )
          }
        }

        // see onDeletePress added below in useFocusEffect

        return {
          table: createEntityTable(defaultProps),
          model: fieldModel,
        }
      } else {
        fieldModel.config.entityListScreenConfig!.onSelection = (_event, item: any) => {
          fieldModel.setEditId(item.id)
        }

        const assocModel = relation.assocModel!
        assocModel.configureRelated(rootEntityModel, params)
        defaultProps.canDeleteAll = true

        // Note: The onAssocPress is put onto the fieldModel, ad the config param will be the config of the fieldsModel, but we will navigate
        // to the assocModel.config.assocScreenRouteNameVal(),
        fieldModel.config.entityListScreenConfig!.onAssocPress = (_event, _config) => {
          appStore.navigate(props.navigation as any, assocModel.config.assocScreenRouteNameVal(), {
            parentRoute: props.route.name,
            rootEntityModel: rootEntityModel,
            relation: relation,
            title: assocModel.config.assocScreenRouteTitleVal(loadedItem),
          })
        }

        if (relation.allowCreatingNewRelated) {
          fieldModel.config.entityListScreenConfig!.onNewPress = (_event) => {
            fieldModel.setEditId(null)
            appStore.navigate(props.navigation as any, fieldModel.config.createFormScreenRouteNameVal(), {
              parentRoute: props.route.name,
              entityModel: fieldModel,
              rootEntityModel: rootEntityModel,
              title: fieldModel.config.createFormScreenRouteTitleVal(),
            })
          }
        }

        fieldModel.config.entityListScreenConfig!.onUnassocPress = (_e, item: any, _config) => {
          const mut = rootEntityModel.unassociate(relation, [item.id])
          mut.then(
            () => {
              fieldModel.reloadList()
            },
            (/*error*/) => {}
          )
        }

        return {
          table: createEntityTable(defaultProps),
          model: relation,
        }
      }
    })

    // Make sure the initial onDeletePress is set for all models\
    setOnDeletePress(res)

    return res
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [rootEntityModel.loadedItem])

  // Redefine onDeletePress on focus, because it is is also used by CreateEditTodoItemScreen
  useFocusEffect(
    React.useCallback(() => {
      setOnDeletePress(tablesAndModels)
      // We could force reloading all the tables in the detail screen this way. This should not be necessary as
      // tables should update/reload when new item added or deleted.
      // tablesAndModels.forEach((tm) => {
      //   // console.log('++++ EntityDetailScreen reloadList ' + tm.table.displayName)
      //   const m = tm.model as EntityModelType
      //   m.reloadList()
      // })
      // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [])
  )

  if (rootEntityModel.loadQueryState == QueryState.ERROR) {
    return <Text>{JSON.stringify(rootEntityModel.loadQueryError)}</Text>
  }

  const loadedItem = rootEntityModel.loadedItem

  return (
    <FormScreen>
      <VStack opacity={loadingOpacity}>
        <Center>
          <Heading pb={5}>
            {loadedItem ? rootEntityModel.config.detailsScreenTitleVal(loadedItem) : 'TOOD: loading'}
          </Heading>
        </Center>
        <HStack alignItems={'center'} space={3}>
          <Heading>
            {loadedItem ? rootEntityModel.config.detailsScreenDataTitleVal(loadedItem) : 'TOOD: loading'}
          </Heading>
          <Button
            leftIcon={<MaterialIcons name="edit" size={20} color="white" />}
            //@ts-ignore
            onPress={(_event) => {
              rootEntityModel.setEditId(rootEntityModel.selectedId)
              appStore.navigate(props.navigation as any, rootEntityModel.config.editFormScreenRouteNameVal(), {
                parentRoute: props.route.name,
                entityModel: rootEntityModel,
                rootEntityModel: rootEntityModel,
                isRootModelCreateEdit: true,
                title: rootEntityModel.config.editFormScreenRouteTitleVal(loadedItem),
              })
            }}
          />
        </HStack>
        <Box p={3} maxW={'600px'}>
          <MyData
            model={rootEntityModel}
            viewId={rootEntityModel.selectedId}
            dataRowGenerator={rootEntityModel.config.dataRowGeneratorVal()}
          />
        </Box>
        {tablesAndModels.map((tableAndModel) => {
          const Table = tableAndModel.table
          return (
            <>
              <SeparatorLine />
              <Table />
            </>
          )
        })}
      </VStack>
    </FormScreen>
  )
})

export default EntityDetailsScreen
