import { computed, defineComponent, inject, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { LoadingElement } from './_ui/functional-loader'
import { ActiviteId, ActiviteIdOrSlug, activiteIdOrSlugValidator, Activite as CommonActivite } from 'camino-common/src/activite'
import { AsyncData } from '@/api/client-rest'
import { Preview } from './activite/preview'
import { ActiviteApiClient, activiteApiClient } from './activite/activite-api-client'
import { canReadActivites } from 'camino-common/src/permissions/activites'
import { User } from 'camino-common/src/roles'
import { CaminoAccessError } from './error'
import { userKey } from '@/moi'

export const Activite = defineComponent(() => {
  const router = useRouter()
  const route = useRoute<'activite'>()
  const user = inject(userKey)

  const activiteId = computed<ActiviteIdOrSlug | null>(() => {
    const idOrSlug = route.params.activiteId
    const validated = activiteIdOrSlugValidator.safeParse(idOrSlug)

    if (validated.success) {
      return validated.data
    }

    return null
  })

  const apiClient = {
    ...activiteApiClient,
    supprimerActivite: async (activiteId: ActiviteId) => {
      await activiteApiClient.supprimerActivite(activiteId)
      router.back()
    },
  }

  return () => <PureActivite user={user} activiteId={activiteId.value} apiClient={apiClient} />
})

interface Props {
  user: User
  activiteId: ActiviteIdOrSlug | null
  apiClient: Pick<ActiviteApiClient, 'getActivite' | 'deposerActivite' | 'supprimerActivite' | 'resetActiviteStatus'>
}
export const PureActivite = defineComponent<Props>(props => {
  const activiteData = ref<AsyncData<CommonActivite>>({ status: 'LOADING' })
  const apiClient: Pick<ActiviteApiClient, 'getActivite' | 'deposerActivite' | 'supprimerActivite' | 'resetActiviteStatus'> = {
    ...props.apiClient,
    deposerActivite: async (activiteId: ActiviteId) => {
      await props.apiClient.deposerActivite(activiteId)
      await retrieveActivite(activiteId)
    },
    resetActiviteStatus: async activiteId => {
      const value = await props.apiClient.resetActiviteStatus(activiteId)
      if ('message' in value) {
        return value
      }
      await retrieveActivite(activiteId)
      return value
    },
  }

  const retrieveActivite = async (activiteId: ActiviteIdOrSlug | null) => {
    if (activiteId === null) {
      activiteData.value = { status: 'ERROR', message: "Id ou slug d'activité non trouvé" }
    } else {
      try {
        activiteData.value = { status: 'LOADING' }
        const data = await props.apiClient.getActivite(activiteId)
        activiteData.value = { status: 'LOADED', value: data }
      } catch (e: any) {
        console.error('error', e)
        activiteData.value = {
          status: 'ERROR',
          message: e.message ?? "Une erreur s'est produite",
        }
      }
    }
  }

  watch(
    () => props.activiteId,
    async () => {
      await retrieveActivite(props.activiteId)
    }
  )

  onMounted(async () => {
    await retrieveActivite(props.activiteId)
  })

  return () => (
    <>
      {canReadActivites(props.user) ? (
        <LoadingElement data={activiteData.value} renderItem={activite => <Preview key={activite.id} activite={activite} apiClient={apiClient} />} />
      ) : (
        <CaminoAccessError user={props.user} />
      )}
    </>
  )
})

// @ts-ignore waiting for https://github.com/vuejs/core/issues/7833
PureActivite.props = ['user', 'activiteId', 'apiClient']
