import { DatePicker } from '@mui/lab'
import { addDays } from 'date-fns/fp'
import {
  Checkbox,
  Button,
  Select,
  FormControl,
  InputLabel,
  MenuItem,
  Stack,
  TextField,
  SelectChangeEvent,
  FormControlLabel,
  Box,
  Typography,
} from '@mui/material'
import Page from 'components/page'
import { format } from 'date-fns'
import useOus, { enSort, nbSort, OuData } from 'hooks/useOus'
import useRoleTypes, { RoleTypeData } from 'hooks/useRoleTypes'
import { Guest } from 'interfaces'
import { useState } from 'react'
import { Controller, useForm } from 'react-hook-form'
import { useTranslation } from 'react-i18next'
import { Link, useHistory, useParams } from 'react-router-dom'
import SponsorInfoButtons from 'routes/components/sponsorInfoButtons'
import { submitJsonOpts } from 'utils'
import { useFeatureContext } from 'contexts/featureContext'

type AddRoleFormData = {
  orgunit: number
  type: string
  end_date: Date
  start_date: Date
  contact_person_unit?: string
  comments?: string
  available_in_search?: boolean
}
type AddRolePayload = {
  orgunit: number
  person: string
  type: string
  end_date: string
  start_date?: string
  contact_person_unit?: string
  comments?: string
  available_in_search?: boolean
}

type GuestInfoParams = {
  pid: string
}

interface NewGuestRoleProps {
  guest: Guest
  reloadGuestInfo: () => void
}

const postRole = async (formData: AddRoleFormData, pid: string) => {
  const payload: AddRolePayload = {
    orgunit: formData.orgunit,
    person: pid,
    type: formData.type,
    end_date: format(formData.end_date as Date, 'yyyy-MM-dd'),
  }
  if (formData.start_date) {
    payload.start_date = format(formData.start_date as Date, 'yyyy-MM-dd')
  }
  if (formData.contact_person_unit) {
    payload.contact_person_unit = formData.contact_person_unit
  }
  if (formData.comments) {
    payload.comments = formData.comments
  }
  if (formData.available_in_search) {
    payload.available_in_search = formData.available_in_search
  }

  console.log('submitting', JSON.stringify(payload))
  fetch('/api/ui/v1/role', submitJsonOpts('POST', payload))
    .then((res) => {
      if (!res.ok) {
        console.log('result', res)
        return null
      }
      console.log('result', res)
      return res.text()
    })
    .then((result) => {
      if (result !== null) {
        console.log('result', result)
      }
    })
    .catch((error) => {
      console.log('error', error)
    })
}

function NewGuestRole({ guest, reloadGuestInfo }: NewGuestRoleProps) {
  const {
    register,
    control,
    handleSubmit,
    formState: { errors },
    setValue,
    getValues,
  } = useForm<AddRoleFormData>()
  const { displayContactAtUnit, displayComment } = useFeatureContext()

  const { pid } = useParams<GuestInfoParams>()
  const history = useHistory()
  const onSubmit = handleSubmit(async () => {
    await postRole(getValues(), pid)
    reloadGuestInfo()
    history.push(`/sponsor/guest/${pid}`)
  })

  const ous = useOus()
  const roleTypes = useRoleTypes()
  const [ouChoice, setOuChoice] = useState<string>('')
  const [roleTypeChoice, setRoleTypeChoice] = useState<string>('')
  const [t, i18n] = useTranslation('common')
  const today = new Date()
  const [maxDate, setMaxDate] = useState(today)

  const todayPlusMaxDays = (roleTypeId?: number) => {
    if (roleTypeId) {
      const role =
        roleTypes === undefined
          ? undefined
          : roleTypes.find((rt) => rt.id === roleTypeId)
      if (role !== undefined) {
        return addDays(role.max_days)(today)
      }
    }
    return addDays(0)(today)
  }

  const roleTypeSort = () => (a: RoleTypeData, b: RoleTypeData) => {
    if (i18n.language === 'en') {
      return a.name_nb.localeCompare(b.name_nb)
    }
    return a.name_en.localeCompare(b.name_en)
  }
  // Handling choices in menus
  const handleRoleTypeChange = (event: SelectChangeEvent) => {
    setValue('type', event.target.value)
    setRoleTypeChoice(event.target.value)
    setMaxDate(todayPlusMaxDays(Number(event.target.value)))
  }
  const handleOuChange = (event: SelectChangeEvent) => {
    if (event.target.value) {
      setOuChoice(event.target.value)
      setValue('orgunit', parseInt(event.target.value, 10))
    }
  }
  // Functions for menu items
  const rolesToItem = (roleType: RoleTypeData) => (
    <MenuItem key={roleType.id.toString()} value={roleType.id}>
      {i18n.language === 'en' ? roleType.name_en : roleType.name_nb}
    </MenuItem>
  )
  // Show ou name in correct language if present. If not use other.
  const ouToItem = (ou: OuData) => {
    let name = ''
    if (i18n.language === 'en') {
      name = ou.en ? ou.en : ou.nb
    } else {
      name = ou.nb ? ou.nb : ou.en
    }
    return (
      <MenuItem key={ou.id.toString()} value={ou.id}>
        {name} ({ou.id})
      </MenuItem>
    )
  }

  return (
    <Page>
      <SponsorInfoButtons
        to={`/sponsor/guest/${pid}`}
        name={`${guest.first} ${guest.last}`}
      />
      <Typography variant="h2">{t('guest.headerText')}</Typography>
      <Typography variant="body1">{t('guest.bodyText')}</Typography>
      <form onSubmit={onSubmit}>
        <Stack spacing={2}>
          <FormControl>
            <InputLabel id="roletype-select-label">
              {t('input.roleType')}
            </InputLabel>
            <Select
              id="roletype-select"
              defaultValue=""
              value={roleTypeChoice}
              error={!!errors.type}
              label={t('input.roleType')}
              onChange={handleRoleTypeChange}
            >
              {(roleTypes === undefined ? [] : roleTypes)
                .sort(roleTypeSort())
                .map((rt) => rolesToItem(rt))}
            </Select>
          </FormControl>

          <FormControl>
            <InputLabel id="ou-select-label-id">{t('common:ou')}</InputLabel>
            <Select
              labelId="ou-select-label"
              id="ou-select-label"
              defaultValue=""
              value={ouChoice.toString()}
              label={t('common:ou')}
              onChange={handleOuChange}
            >
              {ous !== undefined &&
                ous.length > 0 &&
                ous
                  .sort(i18n.language === 'en' ? enSort : nbSort)
                  .map((ou) => ouToItem(ou))}
            </Select>
          </FormControl>
          <Controller
            name="start_date"
            control={control}
            rules={{
              required: true,
              validate: () =>
                Number(getValues('start_date')) <=
                Number(getValues('end_date')),
            }}
            defaultValue={today}
            render={({ field }) => (
              <DatePicker
                mask="____-__-__"
                label={t('input.roleStartDate')}
                disabled={!roleTypeChoice}
                value={field.value}
                maxDate={maxDate}
                inputFormat="yyyy-MM-dd"
                onChange={(value) => {
                  field.onChange(value)
                }}
                renderInput={(params) => <TextField {...params} />}
              />
            )}
          />

          {errors.start_date && errors.start_date.type === 'required' && (
            <Box sx={{ typography: 'caption', color: 'error.main' }}>
              {t('validation.startDateMustBeSet')}
            </Box>
          )}
          {errors.start_date && errors.start_date.type === 'validate' && (
            <Box sx={{ typography: 'caption', color: 'error.main' }}>
              {t('validation.startDateMustBeBeforeEndDate')}
            </Box>
          )}
          <Controller
            name="end_date"
            control={control}
            rules={{
              required: true,
              validate: () =>
                Number(getValues('start_date')) <=
                Number(getValues('end_date')),
            }}
            defaultValue={today}
            render={({ field }) => (
              <DatePicker
                mask="____-__-__"
                label={t('input.roleEndDate')}
                disabled={!roleTypeChoice}
                value={field.value}
                maxDate={maxDate}
                inputFormat="yyyy-MM-dd"
                onChange={(value) => {
                  field.onChange(value)
                }}
                renderInput={(params) => <TextField {...params} />}
              />
            )}
          />
          {displayContactAtUnit && (
            <TextField
              id="contact"
              label={t('input.contactPersonUnit')}
              multiline
              rows={5}
              {...register('contact_person_unit')}
            />
          )}
          {displayComment && (
            <TextField
              id="comments"
              label={t('input.comment')}
              multiline
              rows={5}
              {...register('comments')}
            />
          )}

          <FormControlLabel
            control={
              <Checkbox
                id="available_in_search"
                {...register('available_in_search')}
              />
            }
            label={t('input.searchable')}
          />
          <Button variant="contained" color="secondary" type="submit">
            {t('button.save')}
          </Button>
          <Button
            component={Link}
            color="secondary"
            to={`/sponsor/guest/${pid}`}
          >
            {t('button.cancel')}
          </Button>
        </Stack>
      </form>
    </Page>
  )
}

export default NewGuestRole