import {
  Button,
  FormControl,
  FormControlLabel,
  FormGroup,
  NativeSelect,
  Switch,
  TextField,
} from '@mui/material'
import { DateTime } from 'luxon'
import React, { useCallback, useEffect, useState } from 'react'
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css'
import { useWhoAmI } from '../../API'
import { getAxiosXSRFHeader } from '../../axios.config'
import { CheckboxType } from '../../enum/checkboxType.enum'
import { ICustomPopup, PopupDuration } from '../../models/customPopup.model'
import {
  Option,
  durationEnum,
  durationType,
  mapDuration,
} from '../../models/durationOptions.model'
import { IPartnersInfo } from '../../models/partnersInfo.model'
import { CustomPopupService } from '../../services/customPopup.service'
import { PartnersInfoService } from '../../services/partnersInfo.service'
import { convertStringToEditorState } from '../../utils/editorStateManagement'
import Loader from '../Loader/Loader'
import CustomEditor from '../Newsletter/CustomEditor'
import './popups.scss'

const OPTIONS: Option[] = [
  {
    value: durationEnum.hours,
    label: 'Heures',
  },
  {
    value: durationEnum.days,
    label: 'Jours',
  },
  {
    value: durationEnum.infinite,
    label: 'Indéterminée',
  },
]

const Popups: React.FC = () => {
  const { data: user } = useWhoAmI()

  const [refreshData, setRefreshData] = useState(false)
  const [isLoading, setIsLoading] = useState(false)
  const [partnersInfo, setPartnersInfo] = useState<IPartnersInfo>({
    grdf_failure: false,
    enedis_failure: false,
    egl_failure: false,
    notification_activated: false,
  })
  const [previousEndDate, setPreviousEndDate] = useState<string>()
  const [popupDuration, setPopupDuration] = useState<PopupDuration>({
    type: durationEnum.infinite,
    duration: 5,
  })
  const [customPopup, setCustomPopup] = useState<ICustomPopup>({
    popupEnabled: false,
    title: '',
    description: '',
    endDate: DateTime.local().plus({ days: 365 }).toISO(),
  })

  const isPartnerNotificationOn = () =>
    partnersInfo.enedis_failure ||
    partnersInfo.egl_failure ||
    partnersInfo.grdf_failure

  /** Only one type of popup can be enabled */
  const isPageValid = () =>
    !(isPartnerNotificationOn() && customPopup.popupEnabled)

  const handleCheckboxChange = (value: boolean, type: CheckboxType): void => {
    switch (type) {
      case CheckboxType.GRDF:
        setPartnersInfo(prevPartnersInfo => ({
          ...prevPartnersInfo,
          grdf_failure: value,
        }))
        break
      case CheckboxType.ENEDIS:
        setPartnersInfo(prevPartnersInfo => ({
          ...prevPartnersInfo,
          enedis_failure: value,
        }))
        break
      case CheckboxType.EGL:
        setPartnersInfo(prevPartnersInfo => ({
          ...prevPartnersInfo,
          egl_failure: value,
        }))
        break
      case CheckboxType.CUSTOM:
        setCustomPopup(prev => ({
          ...prev,
          popupEnabled: value,
        }))
        break
      default:
        throw new Error('Unknown checkbox type')
    }
  }

  const handlePopupChange = (field: 'title' | 'description', value: string) => {
    setCustomPopup(prev => ({
      ...prev,
      [field]: value,
    }))
  }

  // clean this
  const handleCancel = useCallback(() => {
    setRefreshData(true)
  }, [setRefreshData])

  const resetFields = useCallback(() => {
    setPartnersInfo({
      grdf_failure: false,
      enedis_failure: false,
      egl_failure: false,
      notification_activated: false,
    })
  }, [setPartnersInfo])

  useEffect(() => {
    let subscribed = true
    resetFields()
    setIsLoading(true)

    async function loadSettings() {
      if (user) {
        const partnersInfoService = new PartnersInfoService()
        const customPopupService = new CustomPopupService()
        const previousPartnersInfo = await partnersInfoService.getPartnersInfo()
        const previousPopup = await customPopupService.getCustomPopupInfo()

        if (previousPartnersInfo) {
          setPartnersInfo({
            ...previousPartnersInfo,
          })
        }
        if (previousPopup) {
          const isOutdated = isPopupOutdated(previousPopup.endDate)
          /** If outdated, set value to false, otherwise, set it to its value */
          const isEnabled = isOutdated ? false : previousPopup.popupEnabled
          setCustomPopup({
            title: previousPopup.title,
            description: previousPopup.description,
            endDate: customPopup.endDate,
            popupEnabled: isEnabled,
          })
          setPreviousEndDate(previousPopup.endDate || undefined)
        }
      }
      setIsLoading(false)
    }
    if (subscribed) {
      loadSettings()
    }
    return () => {
      subscribed = false
      setRefreshData(false)
    }
  }, [user, refreshData, setPartnersInfo, setCustomPopup, resetFields])

  const handleSave = async (): Promise<void> => {
    if (user) {
      const partnersInfoService = new PartnersInfoService()
      const customPopupService = new CustomPopupService()
      const updatedPartnersInfo = {
        egl_failure: partnersInfo.egl_failure,
        enedis_failure: partnersInfo.enedis_failure,
        grdf_failure: partnersInfo.grdf_failure,
        notification_activated: isPartnerNotificationOn(),
      }
      await partnersInfoService.savePartnersInfo(
        updatedPartnersInfo,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      await customPopupService.saveCustomPopup(
        customPopup,
        getAxiosXSRFHeader(user.xsrftoken)
      )
      setPreviousEndDate(customPopup.endDate)
    }
  }

  const handleSelectChange = (event: React.ChangeEvent<HTMLSelectElement>) => {
    setPopupDuration(prev => ({
      ...prev,
      type: event.target.value as durationType,
    }))
  }

  /** Handles duration change */
  useEffect(() => {
    const now = DateTime.local()
    let newDate: DateTime
    if (popupDuration.type !== durationEnum.infinite) {
      newDate = now.plus({
        [popupDuration.type]: popupDuration.duration,
      })
    } else {
      newDate = now.plus({
        years: 1,
      })
    }
    setCustomPopup(prev => ({
      ...prev,
      endDate: newDate.toISO(),
    }))
  }, [popupDuration])

  const isPopupOutdated = (date: string) =>
    DateTime.local() >= DateTime.fromISO(date)

  /**
   * Returns "Popup expirée" OR "Temps restant : ..."
   */
  const getRemainingDuration = (date: string) => {
    if (isPopupOutdated(date)) {
      return <p className="endDate">Popup expirée</p>
    }
    return (
      <p className="endDate">
        Temps d&apos;activation restant :<br />
        {DateTime.fromISO(date)
          .diffNow(['days', 'hours', 'minutes', 'seconds'])
          .set({ second: 0 })
          .toHuman()}
      </p>
    )
  }

  return (
    <>
      <div className="header">
        <h1>Création de Pop-up</h1>
      </div>

      <div className="content popups">
        {isLoading && <Loader />}
        {!isLoading && (
          <>
            <div className="partnersInfo">
              <h3>Affichage des pop-up de panne</h3>
              <div>
                <p>Services concernés</p>
                <FormGroup style={{ flexDirection: 'row' }}>
                  <FormControlLabel
                    label="Panne Enedis"
                    labelPlacement="top"
                    control={
                      <Switch
                        disabled={customPopup.popupEnabled}
                        checked={partnersInfo.enedis_failure}
                        onChange={event => {
                          handleCheckboxChange(
                            event.target.checked,
                            CheckboxType.ENEDIS
                          )
                        }}
                      />
                    }
                  />
                  <FormControlLabel
                    label="Panne EGL"
                    labelPlacement="top"
                    control={
                      <Switch
                        disabled={customPopup.popupEnabled}
                        checked={partnersInfo.egl_failure}
                        onChange={event => {
                          handleCheckboxChange(
                            event.target.checked,
                            CheckboxType.EGL
                          )
                        }}
                      />
                    }
                  />
                  <FormControlLabel
                    label="Panne GRDF"
                    labelPlacement="top"
                    control={
                      <Switch
                        disabled={customPopup.popupEnabled}
                        checked={partnersInfo.grdf_failure}
                        onChange={event => {
                          handleCheckboxChange(
                            event.target.checked,
                            CheckboxType.GRDF
                          )
                        }}
                      />
                    }
                  />
                </FormGroup>
              </div>
            </div>

            <div className="customPopup">
              <h3>Affichage de pop-up personnalisée</h3>
              <FormGroup style={{ flexDirection: 'row' }}>
                <FormControlLabel
                  label="Pop-up active"
                  labelPlacement="top"
                  control={
                    <Switch
                      disabled={isPartnerNotificationOn()}
                      checked={customPopup.popupEnabled}
                      onChange={event => {
                        handleCheckboxChange(
                          event.target.checked,
                          CheckboxType.CUSTOM
                        )
                      }}
                    />
                  }
                />
                {customPopup.popupEnabled &&
                  previousEndDate &&
                  getRemainingDuration(previousEndDate)}
              </FormGroup>

              <div className="popupEndDate">
                <h4>Durée</h4>
                <div>
                  <FormControl style={{ flexDirection: 'row', gap: '1rem' }}>
                    <NativeSelect
                      inputProps={{
                        name: 'age',
                        id: 'uncontrolled-native',
                      }}
                      onChange={event => handleSelectChange(event)}
                      value={popupDuration.type}
                    >
                      {OPTIONS.map(option => (
                        <option key={option.value} value={option.value}>
                          {option.label}
                        </option>
                      ))}
                    </NativeSelect>

                    {popupDuration.type !== 'infinite' && (
                      <TextField
                        style={{ width: '6rem' }}
                        inputProps={{
                          inputMode: 'numeric',
                          pattern: '[0-9]*',
                        }}
                        id="outlined-number"
                        type="number"
                        label={mapDuration[popupDuration.type]}
                        InputLabelProps={{
                          shrink: true,
                        }}
                        value={popupDuration.duration}
                        onChange={e =>
                          setPopupDuration(prev => ({
                            ...prev,
                            duration: Number(e.target.value),
                          }))
                        }
                      />
                    )}
                  </FormControl>
                </div>
              </div>

              <h4>Contenu</h4>
              <div className="popupTitle">
                <TextField
                  type="text"
                  placeholder="Titre de la popup"
                  fullWidth
                  label="Titre"
                  value={customPopup.title}
                  onChange={event =>
                    handlePopupChange('title', event.target.value)
                  }
                />
              </div>

              <div className="popupDescription">
                <CustomEditor
                  baseState={convertStringToEditorState(
                    customPopup.description
                  )}
                  handleChange={value =>
                    handlePopupChange('description', value)
                  }
                  type="custom_popup"
                />
              </div>
            </div>

            <div className="buttons">
              <Button variant="outlined" onClick={handleCancel}>
                Annuler
              </Button>
              <Button disabled={!isPageValid()} onClick={handleSave}>
                Sauvegarder
              </Button>
            </div>
          </>
        )}
      </div>
    </>
  )
}

export default Popups