import { canLinkTitres, getLinkConfig, LinkConfig } from 'camino-common/src/permissions/titres'
import { computed, defineComponent, onMounted, watch } from 'vue'
import { TitreTypeId } from 'camino-common/src/static/titresTypes'
import { User } from 'camino-common/src/roles'
import { AdministrationId } from 'camino-common/src/static/administrations'
import { TitresLink } from './titres-link'
import { AsyncData } from '@/api/client-rest'
import { LoadingElement } from '@/components/_ui/functional-loader'
import { DemarcheTypeId } from 'camino-common/src/static/demarchesTypes'
import { TitreLink, TitreLinks } from 'camino-common/src/titres'
import { TitreId } from 'camino-common/src/validators/titres'
import { ApiClient } from '@/api/api-client'
import { TitresLinkConfig } from '@/components/titre/titres-link-form-api-client'
import { DsfrButtonIcon } from '../_ui/dsfr-button'
import { DsfrIcon } from '../_ui/icon'
import { DsfrTag } from '../_ui/tag'
import { isNotNullNorUndefined, isNotNullNorUndefinedNorEmpty } from 'camino-common/src/typescript-tools'
import { useState } from '@/utils/vue-tsx-utils'
import { FunctionalPopup } from '../_ui/functional-popup'

export interface Props {
  user: User
  titre: {
    id: TitreId
    typeId: TitreTypeId
    administrations: AdministrationId[]
    demarches: { demarche_type_id: DemarcheTypeId }[]
  }
  apiClient: Pick<ApiClient, 'loadTitreLinks' | 'loadLinkableTitres' | 'linkTitres'>
  onTitresFromLoaded: (hasTitresFrom: boolean) => void
}
export const TitresLinkForm = defineComponent<Props>(props => {
  const [popupOpen, setPopupOpen] = useState<boolean>(false)
  const [titresLinks, setTitresLinks] = useState<AsyncData<TitreLinks>>({ status: 'LOADING' })

  const openEditPopup = () => {
    setPopupOpen(true)
  }

  const closeEditPopup = () => {
    setPopupOpen(false)
  }

  const linkConfig = computed(() => getLinkConfig(props.titre.typeId, props.titre.demarches))

  onMounted(async () => {
    await init()
  })

  watch(
    () => props.titre,
    async _ => {
      await init()
    }
  )

  const init = async () => {
    setTitresLinks({ status: 'LOADING' })
    const result = await props.apiClient.loadTitreLinks(props.titre.id)
    if ('message' in result) {
      setTitresLinks({
        status: 'NEW_ERROR',
        error: result,
      })
    } else {
      setTitresLinks({ status: 'LOADED', value: result })
      props.onTitresFromLoaded(result.amont.length > 0)
    }
  }

  const canEditLink = computed<boolean>(() => {
    // On ne peut pas lier si ce type de titre n'accepte pas de liaison
    if (!linkConfig.value) {
      return false
    }

    return canLinkTitres(props.user, props.titre.administrations ?? [])
  })

  const myApiClient = {
    ...props.apiClient,
    linkTitres: async (titreId: TitreId, titreFromIds: TitreId[]) => {
      const links = await props.apiClient.linkTitres(titreId, titreFromIds)
      if (!('message' in links)) {
        setTitresLinks({
          status: 'LOADED',
          value: links,
        })
      }
      return links
    },
  }

  return () => (
    <div>
      <LoadingElement
        data={titresLinks.value}
        renderItem={item => (
          <>
            {(isNotNullNorUndefinedNorEmpty(item.amont) || canEditLink.value) && isNotNullNorUndefined(linkConfig.value) ? (
              <div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }}>
                <DsfrIcon name="fr-icon-link" size="sm" color="text-title-blue-france" aria-hidden="true" />
                {item.amont.length === 0 ? <>Lier {linkConfig.value.count === 'single' ? 'un titre' : 'plusieurs titres'} </> : <>Titre{item.amont.length > 1 ? 's' : ''} à l'origine de ce titre :</>}

                <div class="flex flex-center" style={{ gap: '0.5rem' }}>
                  {item.amont.map(titreFrom => (
                    <DsfrTag key={titreFrom.id} tagSize="sm" to={{ name: 'titre', params: { id: titreFrom.id } }} ariaLabel={titreFrom.nom} />
                  ))}

                  {canEditLink.value ? <DsfrButtonIcon buttonType="tertiary-no-outline" title="modifier les titres liés" onClick={openEditPopup} icon="fr-icon-pencil-line" /> : null}
                </div>
              </div>
            ) : null}

            {item.aval.length ? (
              <div style={{ display: 'flex', gap: '0.5rem', alignItems: 'center' }} class="fr-mt-1w">
                <DsfrIcon name="fr-icon-link" size="sm" color="text-title-blue-france" aria-hidden="true" />
                {item.aval.length > 1 ? 'Titres issus ' : 'Titre issu'} de ce titre :
                <div class="flex flex-center" style={{ gap: '0.5rem' }}>
                  {item.aval.map(titreTo => (
                    <DsfrTag key={titreTo.id} tagSize="sm" to={{ name: 'titre', params: { id: titreTo.id } }} ariaLabel={titreTo.nom} />
                  ))}
                </div>
              </div>
            ) : null}
            {popupOpen.value && isNotNullNorUndefined(linkConfig.value) ? (
              <EditPopup titreLinks={item} linkConfig={linkConfig.value} close={closeEditPopup} apiClient={myApiClient} titre={props.titre} />
            ) : null}
          </>
        )}
      />
    </div>
  )
})

interface EditPopupProps {
  titreLinks: TitreLinks
  linkConfig: LinkConfig
  titre: {
    id: TitreId
    typeId: TitreTypeId
    administrations: AdministrationId[]
    demarches: { demarche_type_id: DemarcheTypeId }[]
  }
  close: () => void
  apiClient: Pick<ApiClient, 'loadTitreLinks' | 'loadLinkableTitres' | 'linkTitres'>
}

const EditPopup = defineComponent<EditPopupProps>(props => {
  const [selectedTitres, setSelectedTitres] = useState<TitreLink[]>([])
  const onSelectedTitres = (titres: TitreLink[]) => {
    setSelectedTitres(titres)
  }
  const titreLinkConfig = computed<TitresLinkConfig>(() => {
    const titreFromIds = props.titreLinks.amont.map(({ id }) => id)
    if (props.linkConfig.count === 'single') {
      return {
        type: 'single',
        selectedTitreId: titreFromIds.length === 1 ? titreFromIds[0] : null,
      }
    }

    return {
      type: 'multiple',
      selectedTitreIds: titreFromIds,
    }
  })

  const content = () => (
    <form>
      <TitresLink config={titreLinkConfig.value} loadLinkableTitres={props.apiClient.loadLinkableTitres(props.titre.typeId, props.titre.demarches)} onSelectTitres={onSelectedTitres} />
    </form>
  )

  return () => (
    <FunctionalPopup
      title="Modification des liens entre les titres"
      content={content}
      close={props.close}
      validate={{
        action: () =>
          props.apiClient.linkTitres(
            props.titre.id,
            selectedTitres.value.map(({ id }) => id)
          ),
        text: 'Enregistrer',
      }}
      canValidate={true}
    />
  )
})

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

// @ts-ignore waiting for https://github.com/vuejs/core/issues/7833
EditPopup.props = ['apiClient', 'titre', 'titreLinks', 'linkConfig', 'close']
