import React, { useEffect, useState } from 'react';
import { useRef } from 'react';
import { useOutletContext } from 'react-router-dom';
import {
  Alert,
  Button,
  FormControl,
  FormControlLabel,
  FormLabel,
  Grid,
  Paper,
  Radio,
  RadioGroup,
  Snackbar,
  TextField,
} from '@mui/material';
import MailIcon from '@mui/icons-material/Mail';
import { useForm, Controller, useFieldArray } from 'react-hook-form';
import { useUpdateGuestMutation } from '../slices/api/guestSlice';
import type { Guest } from '../models';

interface StatusProps {
  isError: boolean;
  setOpen: (open: boolean) => void;
}

const Status = ({ isError, setOpen }: StatusProps) => {
  return isError ? (
    <Alert severity="error" onClose={() => setOpen(false)}>
      RSVP failed
    </Alert>
  ) : (
    <Alert severity="success" onClose={() => setOpen(false)}>
      RSVP updated
    </Alert>
  );
};

function RsvpForm() {
  const [updateGuest, { isLoading, isSuccess, isError, error }] =
    useUpdateGuestMutation();
  const guest: Guest = useOutletContext();
  const previousPartySize = useRef(guest?.partySize - 1);
  const [open, setOpen] = useState<boolean>(false);

  useEffect(() => {
    setOpen(isSuccess || isError);
  }, [isSuccess, isError]);

  const {
    register,
    handleSubmit,
    control,
    watch,
    formState: { errors },
  } = useForm<Guest>({
    defaultValues: {
      id: guest?.id,
      firstName: guest?.firstName,
      lastName: guest?.lastName,
      attendance: guest?.attendance,
      email: guest?.email,
      message: guest?.message,
      partySize: guest?.partySize,
      partyList: guest?.partyList,
    },
  });

  const onSubmit = async (data: Guest) => {
    updateGuest({ ...data });
  };

  const { fields, append, remove } = useFieldArray({
    control,
    name: 'partyList',
  });

  const handleParty = () => {
    const partySize = Number(watch('partySize')) - 1;
    if (
      partySize > previousPartySize.current &&
      partySize > 0 &&
      partySize < 10
    ) {
      append(
        new Array(partySize - previousPartySize.current).fill({
          firstName: '',
          lastName: '',
        })
      );
      previousPartySize.current = partySize;
    } else if (partySize < previousPartySize.current && partySize >= 0) {
      remove(
        [...Array(previousPartySize.current - partySize).keys()].map(
          (_, i) => partySize - 1 + i
        )
      );
      previousPartySize.current = partySize;
    }
  };

  return (
    <form
      style={{
        height: '100%',
        width: '100%',
        display: 'flex',
        justifyContent: 'center',
        alignItems: 'start',
      }}
      noValidate
      onSubmit={handleSubmit(onSubmit)}
    >
      <Paper
        elevation={3}
        sx={{
          '&:hover': { boxShadow: 8 },
          width: { xs: '90%', md: 600 },
          display: 'flex',
          justifyContent: 'center',
          px: 2,
          pb: 2,
          mt: { xs: 10, md: 16 },
          borderRadius: '8px',
        }}
      >
        <Grid container spacing={2}>
          <Grid item xs={12}>
            <p>
              Please RSVP for the wedding by March 10, 2025. The ceremony will
              commence at 2 PM on April 26 in Divine Shepherd. The reception
              will follow at 5 PM in A Venue on the Ridge.
            </p>
          </Grid>
          <Grid item xs={12}>
            <div style={{ display: 'flex', justifyContent: 'center' }}>
              <FormControl>
                <div style={{ display: 'flex', alignItems: 'center' }}>
                  <FormLabel
                    sx={{ mr: 2 }}
                    error={!!errors.attendance}
                    required
                  >
                    Attendance
                  </FormLabel>
                  <Controller
                    name="attendance"
                    control={control}
                    rules={{ required: true }}
                    render={({ field }) => (
                      <RadioGroup {...field} row>
                        <FormControlLabel
                          value="accept"
                          control={<Radio />}
                          label="Accept"
                        />
                        <FormControlLabel
                          value="decline"
                          control={<Radio />}
                          label="Decline"
                        />
                      </RadioGroup>
                    )}
                  />
                </div>
              </FormControl>
            </div>
          </Grid>
          <Grid item xs={8}>
            <TextField
              label="Email"
              type="email"
              variant="outlined"
              fullWidth
              error={!!errors.email}
              helperText={errors.email?.message}
              required
              {...register('email', {
                setValueAs: (value: string) => value.trim(),
                required: 'This field is required',
                pattern: {
                  value: /\S+@\S+\.\S+/,
                  message: 'Please enter a valid email address',
                },
              })}
            />
          </Grid>
          <Grid item xs={4}>
            <TextField
              label="Party Size"
              type="number"
              variant="outlined"
              fullWidth
              onWheel={(event) => {
                event.currentTarget.blur();
              }}
              error={!!errors.partySize}
              helperText={errors.partySize?.message}
              required
              {...register('partySize', {
                valueAsNumber: true,
                onChange: handleParty,
                required: 'This field is required',
                min: { value: 1, message: 'Please enter a positive integer' },
                max: {
                  value: 9,
                  message: 'Please enter an integer less than 10',
                },
              })}
            />
          </Grid>
          <Grid item xs={12}>
            <TextField
              label="Message to the couple"
              variant="outlined"
              fullWidth
              multiline
              rows={3}
              {...register('message')}
            />
          </Grid>
          {fields.map((field, index) => {
            return (
              <Grid
                container
                item
                columnSpacing={2}
                rowSpacing={{ xs: 1 }}
                key={field.id}
              >
                <Grid item xs={6}>
                  <TextField
                    label="First Name"
                    variant="outlined"
                    fullWidth
                    error={!!errors.partyList?.[index]?.firstName}
                    helperText={errors.partyList?.[index]?.firstName?.message}
                    required
                    {...register(`partyList.${index}.firstName`, {
                      setValueAs: (value: string) => value.trim(),
                      required: 'This field is required',
                    })}
                  />
                </Grid>
                <Grid item xs={6}>
                  <TextField
                    label="Last Name"
                    variant="outlined"
                    fullWidth
                    error={!!errors.partyList?.[index]?.lastName}
                    helperText={errors.partyList?.[index]?.lastName?.message}
                    required
                    {...register(`partyList.${index}.lastName`, {
                      setValueAs: (value: string) => value.trim(),
                      required: 'This field is required',
                    })}
                  />
                </Grid>
              </Grid>
            );
          })}
          <Grid item xs={12}>
            <div
              style={{
                display: 'flex',
                flexDirection: 'column',
                alignItems: 'center',
              }}
            >
              <Button
                type="submit"
                variant="contained"
                startIcon={<MailIcon />}
              >
                RSVP
              </Button>
            </div>
          </Grid>
          <Snackbar
            open={!isLoading && open}
            onClose={() => setOpen(false)}
            autoHideDuration={5000}
          >
            <div>
              <Status isError={isError} setOpen={setOpen} />
            </div>
          </Snackbar>
        </Grid>
      </Paper>
    </form>
  );
}

export default RsvpForm;
