import {useCallback, useEffect, forwardRef, useState} from 'react'
import {styled} from '@mui/material/styles'
import PropTypes from 'prop-types'
import axios from 'axios'
import {useSession} from 'next-auth/react'
import {
  Box,
  Button,
  Container,
  FormControl,
  FormHelperText,
  Grid,
  IconButton,
  InputAdornment,
  InputLabel,
  LinearProgress,
  OutlinedInput,
  Snackbar,
  TextField,
  Tooltip,
  Typography
} from '@mui/material'
import MuiAlert from '@mui/material/Alert'
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff'

import AjouteTradiksyon from './ajoute-tradiksyon'

const PREFIX = 'EkriTeks'

const classes = {
  tooltip: `${PREFIX}-tooltip`
}

const StyledContainer = styled(Container)(() => ({
  [`& .${classes.tooltip}`]: {
    fontSize: 18
  }
}))

const API_URL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:1337'

const textLabels = {
  fr: {
    title: 'Traduction',
    help: 'Traduction des paroles',
    emoji: '&#127467;&#127479;'
  },
  en: {
    title: 'Translation',
    help: 'Translation of the lyrics',
    emoji: '&#127468;&#127463;'
  },
  es: {
    title: 'Traducción',
    help: 'Traducción de la letra',
    emoji: '&#127466;&#127480;'
  },
  de: {
    title: 'Übersetzung',
    help: 'Übersetzung von Liedtexten',
    emoji: '&#127465;&#127466;'
  },
  it: {
    title: 'Traduzione',
    help: 'Traduzione del testo',
    emoji: '&#127470;&#127481;'
  }
}

const Alert = forwardRef(function Alert(props, ref) {
  return <MuiAlert ref={ref} elevation={6} variant='filled' {...props} />
})

const RemoveTooltip = Tooltip

function EkriTeks({canAutoTranslate, selectedTeks, setSelectedTeks}) {
  const {data: session} = useSession()
  const {jwt, user} = session
  const [teksEkri, setTeksEkri] = useState({awtis: '', tit: '', transkripsyon: ''})
  const [tradiksyon, setTradiksyon] = useState({fr: '', en: '', es: '', de: '', it: ''})
  const [kiChawLang, setKiChwalang] = useState(['fr'])
  const [error, setError] = useState('')
  const [success, setSuccess] = useState('')
  const [loading, setLoading] = useState(false)
  const [currentTeksId, setCurrentTeksId] = useState(null)
  const [open, setOpen] = useState(false)
  const [tradiksyonOtomatik, setTradiksyonOtomatik] = useState(false)

  const handleUpdate = useCallback(update => {
    setTeksEkri({...teksEkri, ...update})
  }, [teksEkri])

  const handleUpdateTradiksyon = useCallback(update => {
    setTradiksyon({...tradiksyon, ...update})
  }, [tradiksyon])

  const handleRemoveTradiksyon = useCallback(idTradiksyon => {
    setKiChwalang(kiChawLang.filter(t => t !== idTradiksyon))
  }, [kiChawLang, setKiChwalang])

  const handleClose = (event, reason) => {
    if (reason === 'clickaway') {
      return
    }

    setOpen(false)
    setSuccess('')
    setError('')
  }

  const handleClick = () => {
    setLoading(true)
    const {awtis, tit, transkripsyon} = teksEkri
    const {fr, en, es, de, it} = tradiksyon

    if (teksEkri.awtis === '' || teksEkri.tit === '' || teksEkri.transkripsyon === '') {
      setError({message: 'Certains champs sont obligatoires'})
      setLoading(false)

      return
    }

    const headers = {
      'content-type': 'application/json',
      Authorization: `Bearer ${jwt}`
    }

    if (currentTeksId) {
      axios.get(`${API_URL}/teks/${currentTeksId}?_publicationState=preview&_where[published_at_null]=true`)
        .then(awtisResponse => {
          if (awtisResponse.data.user.id !== user.id) {
            setLoading(false)
            return setError({message: 'Opération non autorisée'})
          }

          axios.put(`${API_URL}/teks/${currentTeksId}`, {
            tit,
            transkripsyon,
            tradiksyon: {
              francais: fr === '' ? null : fr,
              english: en === '' ? null : en,
              espagnol: es === '' ? null : es,
              deutsch: de === '' ? null : de,
              italiano: it === '' ? null : it
            },
            user,
            awtis: awtisResponse.data.awtis.map(id => id),
            tradiksyonOtomatik
          }, {
            headers
          })
            .then(teksResponse => {
              const {data} = teksResponse
              setSuccess(`Le texte "${data.tit}" a été modifié avec succès. Il apparaîtra sur le site après validation.`)
              setLoading(false)
            })
            .catch(error => {
              setError(error)
              setLoading(false)
            })
        })
        .catch(error => {
          setError(error)
          setLoading(false)
        })
    } else {
      axios.post(`${API_URL}/awtis`, {
        alias: awtis,
        user
      }, {
        headers
      })
        .then(awtisResponse => {
          axios.post(`${API_URL}/teks`, {
            tit,
            transkripsyon,
            tradiksyon: {
              francais: fr === '' ? null : fr,
              english: en === '' ? null : en,
              espagnol: es === '' ? null : es,
              deutsch: de === '' ? null : de,
              italiano: it === '' ? null : it
            },
            user,
            awtis: [awtisResponse.data.id],
            tradiksyonOtomatik
          }, {
            headers
          })
            .then(teksResponse => {
              const {data} = teksResponse
              setSuccess(`Le texte "${data.tit}" a été soumis avec succès. Il apparaîtra sur le site après validation.`)
              setLoading(false)
            })
            .catch(error => {
              setError(error)
              setLoading(false)
            })
        })
        .catch(error => {
          setError(error)
          setLoading(false)
        })
    }
  }

  const handleReset = () => {
    setTeksEkri({awtis: '', tit: '', transkripsyon: ''})
    setTradiksyon({fr: '', en: '', es: '', de: '', it: ''})
    setKiChwalang(['fr'])
    setCurrentTeksId(null)
    setTradiksyonOtomatik(false)
  }

  useEffect(() => {
    if (success) {
      setOpen(true)
      handleReset()
    }
  }, [success])

  useEffect(() => {
    if (error) {
      setOpen(true)
    }
  }, [error])

  useEffect(() => {
    if (selectedTeks) {
      setTradiksyonOtomatik(false)
      setCurrentTeksId(selectedTeks.id)
      setTeksEkri({
        awtis: new Intl.ListFormat('fr').format(selectedTeks.awtis.map(({alias}) => alias)),
        tit: selectedTeks.tit,
        transkripsyon: selectedTeks.transkripsyon
      })
      setTradiksyon({
        fr: selectedTeks.tradiksyon.francais || '',
        en: selectedTeks.tradiksyon.english || '',
        es: selectedTeks.tradiksyon.espagnol || '',
        de: selectedTeks.tradiksyon.deutsch || '',
        it: selectedTeks.tradiksyon.italiano || ''
      })

      const jennLangId = () => {
        const ids = []
        const {francais, english, espagnol, deutsch, italiano} = selectedTeks.tradiksyon

        if (francais) {
          ids.push('fr')
        }

        if (english) {
          ids.push('en')
        }

        if (espagnol) {
          ids.push('es')
        }

        if (deutsch) {
          ids.push('de')
        }

        if (italiano) {
          ids.push('it')
        }

        return ids
      }

      const langIds = jennLangId()

      setKiChwalang(langIds)
    }

    return () => {
      setSelectedTeks(null)
    }
  }, [teksEkri, selectedTeks, setSelectedTeks, kiChawLang])

  return (
    <StyledContainer maxWidth='sm'>
      <Box sx={{textAlign: 'center', marginBottom: 2}}>
        <Typography display='inline' variant='h6' component='h1'>
          Soumettre un texte
        </Typography>
      </Box>
      <form noValidate autoComplete='off'>
        <Grid container style={{textAlign: 'center'}} spacing={1}>
          <Grid item xs>
            <TextField
              required
              id='awtis'
              name='awtis'
              label='Artiste'
              value={teksEkri.awtis}
              disabled={Boolean(currentTeksId)}
              variant='outlined'
              helperText='Nom de l’artiste (obligatoire)'
              onChange={event => handleUpdate({awtis: event.target.value})}
            />
          </Grid>
          <Grid item xs>
            <TextField
              required
              id='tit'
              name='tit'
              label='Titre'
              value={selectedTeks?.tit || teksEkri.tit}
              variant='outlined'
              helperText='Titre de la musique (obligatoire)'
              onChange={event => handleUpdate({tit: event.target.value})}
            />
          </Grid>
        </Grid>
        <TextField
          fullWidth
          multiline
          required
          helperText='Transcription des paroles (obligatoire)'
          style={{marginTop: '1em'}}
          id='transkripsyon'
          label='Transcription'
          value={teksEkri.transkripsyon}
          rows={8}
          variant='outlined'
          onChange={event => handleUpdate({transkripsyon: event.target.value})}
        />
        {kiChawLang.length > 0 && kiChawLang.map(k => (
          <FormControl key={k} fullWidth style={{marginBlock: 10}}>
            <InputLabel htmlFor={`tradiksyon-${k}`}>
              <span dangerouslySetInnerHTML={{__html: textLabels[k].emoji}} /> {textLabels[k].title}
            </InputLabel>
            <OutlinedInput
              multiline
              style={{marginTop: '1em'}}
              id={`tradiksyon-${k}`}
              name={`tradiksyon-${k}`}
              label={`${textLabels[k].title}`}
              value={tradiksyon[k]}
              rows={8}
              endAdornment={
                <InputAdornment position='end'>
                  <RemoveTooltip
                    title='Cacher la fenêtre'
                    placement='left'
                    classes={{
                      tooltip: classes.tooltip
                    }}
                  >
                    <IconButton
                      style={{bottom: 75}}
                      aria-label='remove-tradiksyon'
                      edge='end'
                      size='large'
                      onClick={() => handleRemoveTradiksyon(k)}
                    >
                      <VisibilityOffIcon />
                    </IconButton>
                  </RemoveTooltip>
                </InputAdornment>
              }
              onChange={event => handleUpdateTradiksyon({[k]: event.target.value})}
            />
            <FormHelperText id={`tradiksyon-${k}`}>{textLabels[k].help}</FormHelperText>
          </FormControl>
        ))}
      </form>
      <AjouteTradiksyon
        showSwitch={Boolean(canAutoTranslate) && Boolean(!currentTeksId)}
        disableSwitch={tradiksyon.fr === ''}
        tradiksyonOtomatik={tradiksyonOtomatik}
        setTradiksyonOtomatik={setTradiksyonOtomatik}
        chwaLang={kiChawLang}
        setChwaLang={setKiChwalang}
      />
      <div>
        <Button
          fullWidth
          disabled={loading || teksEkri.awtis === '' || teksEkri.tit === '' || teksEkri.transkripsyon === ''}
          style={{marginTop: 20}}
          variant='contained'
          color='primary'
          onClick={handleClick}
        >
          <Typography style={{fontWeight: 'bold'}}>
            Valider
          </Typography>
        </Button>
        <Button
          fullWidth
          disabled={loading || (teksEkri.awtis === '' && teksEkri.tit === '' && teksEkri.transkripsyon === '')}
          style={{marginTop: 20}}
          variant='contained'
          color='secondary'
          onClick={handleReset}
        >
          <Typography style={{fontWeight: 'bold'}}>
            Tout effacer
          </Typography>
        </Button>
        {loading && <LinearProgress size={24} style={{width: '100%', marginBlock: '1em'}} />}
      </div>
      {success && (
        <Snackbar open={open} autoHideDuration={10_000} onClose={handleClose}>
          <Alert severity='success' onClose={handleClose}>
            <strong>{success}</strong>
          </Alert>
        </Snackbar>
      )}
      {error && (
        <Snackbar open={open} autoHideDuration={6000} onClose={handleClose}>
          <Alert severity='error' onClose={handleClose}>
            <strong>Une erreur s’est produite</strong> : <i>{error.message}</i>
          </Alert>
        </Snackbar>
      )}
    </StyledContainer>
  )
}

EkriTeks.defaultProps = {
  selectedTeks: null,
  canAutoTranslate: null
}

EkriTeks.propTypes = {
  canAutoTranslate: PropTypes.bool,
  selectedTeks: PropTypes.object,
  setSelectedTeks: PropTypes.func.isRequired,
}

export default EkriTeks
