import * as Yup from 'yup';
import { useCallback, useState, useEffect } from 'react';
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import Box from '@mui/material/Box';
import Stack from '@mui/material/Stack';
import Button from '@mui/material/Button';
import Tooltip from '@mui/material/Tooltip';
import IconButton from '@mui/material/IconButton';
import LoadingButton from '@mui/lab/LoadingButton';
import DialogActions from '@mui/material/DialogActions';
import { MobileDateTimePicker } from '@mui/x-date-pickers/MobileDateTimePicker';
import uuidv4 from '@/utils/uuidv4';
import { isAfter, fTimestamp } from '@/utils/format-time';
import { createEvent, updateEvent, deleteEvent, createRecurrent, useGetEvents, searchForUserByQuery, updateRecurrent } from '@/shared/api/calendar';
import Iconify from '@/shared/components/iconify';
import { useSnackbar } from '@/shared/components/snackbar';
import { ColorPicker } from '@/shared/components/color-utils';
import FormProvider, { RHFSwitch, RHFTextField, RHFEditor, RHFAutocomplete } from '@/shared/components/hook-form';
import { ICalendarDate, ICalendarEvent, DialogData, getDayOfWeek, ICalendarEventWithRecurrent } from '@/shared/types/calendar';
import TextField from '@mui/material/TextField';
import moment from 'moment-timezone';
import MenuItem from '@mui/material/MenuItem';
import { RHFSelect, RHFMultiSelect } from '@/shared/components/hook-form';
import { Dialog, DialogTitle, DialogContent } from '@mui/material';
import IncrementerButton from './incrementer-button';
import Typography from '@mui/material/Typography';
import { formHelperTextClasses } from '@mui/material/FormHelperText';
import { DAYS_NAME_OPTIONS } from '@/shared/types/calendar';
import Select from '@mui/material/Select';
import React, { ChangeEvent } from 'react';
import { SelectChangeEvent } from '@mui/material';
import Chip from '@mui/material/Chip';
import { DatePicker } from '@mui/x-date-pickers/DatePicker';
import { getUserById } from '@/shared/api/user';


// ----------------------------------------------------------------------



type Props = {
  colorOptions: string[];
  onClose: VoidFunction;
  currentEvent?: ICalendarEventWithRecurrent;
};

export default function CalendarForm({ currentEvent, colorOptions, onClose }: Props) {

  const { enqueueSnackbar } = useSnackbar();
  const [guests, setGuests] = useState<string[]>([]);
  const [guestsEmails, setGuestsEmails] = useState<string[]>([]);
  const [selectedTimezone, setSelectedTimezone] = useState<string | null>(null);

  const handleAddGuest = () => {
    // setGuests([...guests, '']);
    setGuestsEmails([...guestsEmails, '']);
  };

  useEffect(() => {
    setSelectedTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
    setRecurring(currentEvent?.recurring?.happens || 'at one time');
    if (currentEvent?.guests && currentEvent.guests.length > 0) {
      (async () => {
        try {
          const allGuestsData = await Promise.all(
            currentEvent.guests.map(async (guestId) => {
              const data = await getUserById(Number(guestId));
              return { id: String(data.id), email: data.email };
            })
          );

          setGuests(allGuestsData.map((guest) => guest.id));
          setGuestsEmails(allGuestsData.map((guest) => guest.email));
        } catch (error) {
          console.error(error);
        }
      })();
    }
  }, [currentEvent?.guests]);



  const allTimezones = moment.tz.names().map((timezone) => ({
    value: timezone,
    label: `(GMT${moment.tz(timezone).format('Z')}) ${timezone}`,
  }));


  const [selectedDays, setSelectedDays] = useState<string[]>([]);

  const [happens, setHappens] = useState<string>('');
  const handleHappensChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setHappens(event.target.value as string);
    setDialogData({ ...dialogData, happens: event.target.value as string });
  };

  const [every, setEvery] = useState<number>(1);
  const handleEveryChange = (newValue: number) => {
    setEvery(newValue);
    setDialogData({ ...dialogData, every: newValue });
  };

  const [ends, setEnds] = useState<string>('');
  const [endsOption, setEndsOption] = useState<string | null>(null);
  const handleEndsChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    setEnds(event.target.value as string);
    setEndsOption(event.target.value as string);
    setDialogData({ ...dialogData, ends: event.target.value as string });
  };

  const [selectedDate, setSelectedDate] = useState<Date | null>(null);
  const handleDateChange = (date: Date | null) => {
    setSelectedDate(date);
    setDialogData({ ...dialogData, selectedDate: date });
  };

  const [selectedStartDate, setSelectedStartDate] = useState<Date | null>(null);

  const handleSelectChange = (event: SelectChangeEvent<string[]>) => {
    setSelectedDays(event.target.value as string[]);
    setDialogData({ ...dialogData, selectedDays: event.target.value as string[] });
  };

  const [monthlyOption, setMonthlyOption] = useState<string>('');
  const handleMonthlyOptionChange = (event: SelectChangeEvent<string>) => {
    const newValue = event.target.value;
    setMonthlyOption(newValue);
    console.log("monthlyOption", monthlyOption);

    setDialogData((prevData: DialogData) => ({ ...prevData, monthlyOptions: newValue }));
  };

  const handleOccurrenceChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    const value = event.target.value;
    const parsedValue = parseInt(value, 10);
    if (!isNaN(parsedValue)) {
      setDialogData({ ...dialogData, occurrences: parsedValue });
    }
  };

  const [recurring, setRecurring] = useState<string>('at one time');

  const handleRecurringOptionChange = (event: React.ChangeEvent<{ value: unknown }>) => {
    console.log("recurring event " + recurring );
    if (event.target.value === 'personnaliser') {
      handleOpenDialog();
    } else {
      console.log("erreur dans l'ouverture de dialogue");
    }
  };

  const [dialogData, setDialogData] = useState<DialogData | any>({
    happens: '',
    id: null,
    every: 1,
    selectedDays: [],
    ends: '',
    selectedDate: null,
    monthlyOptions: '',
    occurrences: 0,
  });

  const [open, setOpen] = useState<boolean>(false);
  const handleOpenDialog = () => {
    setOpen(true);
  };
  const handleCloseDialog = () => {
    setOpen(false);
  };

  const [openUserSearch, setOpenUserSearch] = useState<boolean>(false);
  const handleOpenDialogUserSearch = () => {
    setOpenUserSearch(true);
  };
  const handleCloseDialogUserSearch = () => {
    console.log('Date selected:', selectedDate);
    setOpenUserSearch(false);
  };
  const [currentRecurrent, setCurrentRecurrent] = useState<DialogData | any>();
  const handleSaveDialog = () => {
    if (dialogData.id) {
      updateRecurrent(dialogData.id, dialogData).then((data) => {
        setDialogData(data);
        setCurrentRecurrent(data);
      });
    } else {
      createRecurrent(dialogData).then((data) => {
        setDialogData(data);
        setCurrentRecurrent(data);
      });
    }
    
    handleCloseDialog();
  };


  const EventSchema = Yup.object().shape({
    title: Yup.string().max(255).required('Title is required'),
    description: Yup.string().max(5000, 'Description must be at most 5000 characters').required('Description is required'),
    color: Yup.string(),

    start: Yup.date()
      .transform((value, originalValue) => (originalValue ? new Date(originalValue) : value))
      .required('Start date is required')
      .test('is-future', 'Start date must be later than now', function (value) {
        const now = new Date();
        now.setHours(0, 0, 0, 0);
        return value && new Date(value) > now;
      }),

    end: Yup.date()
      .transform((value, originalValue) => (originalValue ? new Date(originalValue) : value))
      .required('End date is required')
      .test('is-future', 'End date must be later than now', function (value) {
        const now = new Date();
        now.setHours(0, 0, 0, 0);
        return value && new Date(value) > now;
      })
      .test('is-greater', 'End date must be later than start date', function (value) {
        const { start } = this.parent;
        return value && start ? new Date(value) > new Date(start) : false;
      }),


    guests: Yup.array().of(Yup.string()),
    timeZone: Yup.string(),
    notification: Yup.string(),
    recurring: Yup.mixed(),
  });

  const methods = useForm({
    resolver: yupResolver(EventSchema),
    defaultValues: {
      title: currentEvent?.title || '',
      description: currentEvent?.description || '',
      color: currentEvent?.color || '',
      start: currentEvent?.start ? new Date(currentEvent.start) : new Date(),
      end: currentEvent?.end ? new Date(currentEvent.end) : new Date(),
      guests: currentEvent?.guests || [],
      timeZone: currentEvent?.timeZone || '',
      notification: currentEvent?.notification || '',
      recurring: currentEvent?.recurring || '',
    },
  });

  const {
    reset,
    watch,
    control,
    handleSubmit,
    formState: { isSubmitting, errors },
  } = methods;

  const values = watch();
  const dateError = isAfter(values.start, values.end);

  useEffect(() => {
    setSelectedStartDate(new Date(methods.watch('start')));
  }, [methods]);

  const onSubmit = handleSubmit(async (data) => {
    try {
      if (!dateError) {
        // Handle recurrent data
        let recurrentId: number | null = null;
        
        // If we have current recurrent data with an ID, use it
        if (currentEvent?.recurring?.id) {
          recurrentId = currentEvent.recurring.id;
        }
        
        // If we have new dialog data with an ID from creation/update, use that instead
        if (dialogData?.id) {
          recurrentId = dialogData.id;
        }

        // Prepare event data
        const eventData: ICalendarEvent = {
          id: currentEvent?.id || '',
          color: data?.color || '',
          title: data?.title || '',
          description: data?.description || '',
          end: data?.end || new Date(),
          start: data?.start || new Date(),
          guests: guests,
          timeZone: data?.timeZone || '',
          notification: data?.notification || '',
          recurring: recurrentId || 0,
        };
  
        // Add recurrent ID to event data
        if (recurrentId) {
          eventData.recurring = recurrentId;
        }
  
        // Create or update event
        if (currentEvent?.id) {
          await updateEvent({
            ...eventData,
            id: currentEvent.id,
            end: new Date(eventData.end),
            start: new Date(eventData.start),
            recurring: { id: recurrentId || 0 } as DialogData
          });
          enqueueSnackbar('Update success!');
        } else {
          await createEvent(eventData);
          enqueueSnackbar('Create success!');
        }
        
        onClose();
        reset();
      }
    } catch (error) {
      console.error('Error saving event:', error);
      enqueueSnackbar('Error saving event', { variant: 'error' });
    }
  });

  const onDelete = useCallback(async () => {
    try {
      await deleteEvent(`${currentEvent?.id}`);
      enqueueSnackbar('Delete success!');
      onClose();
    } catch (error) {
      console.error(error);
    }
  }, [currentEvent?.id, enqueueSnackbar, onClose]);

  type GuestType = {
    id: number;
    email: string;
  }

  const [users, setUsers] = useState<GuestType[]>([]);
  const [query, setQuery] = useState<string>("");
  const [email, setEmail] = useState<string>("");
  const [selectedUserId, setSelectedUserId] = useState<number | null>(null);

  useEffect(() => {
    if (query && query.length >= 2) {
      searchForUser(query);
    }
  }, [query]);

  const searchForUser = async (search: string) => {
    try {
      const searchedUsers = await searchForUserByQuery(search);
      setUsers(searchedUsers.map((user: any) => ({
        id: user.id,
        email: user.email
      })));
    } catch (error) {
      enqueueSnackbar('Enter more than 2 characters while searching for user', { variant: 'error' });
    }
  }

  const handlePutQuery = (event: any) => {
    setQuery(event.target.value);
  }

  const pickUser = () => {
    if (selectedUserId !== null && email) {
      if (!guests.includes(String(selectedUserId))) {
        const updatedGuests = [...guests, String(selectedUserId)];
        const updatedGuestsEmails = [...guestsEmails, email];

        setGuests(updatedGuests);
        setGuestsEmails(updatedGuestsEmails);

        console.log("Updated guests array:", updatedGuests);
      }
      setOpenUserSearch(false);
      setSelectedUserId(null);
      setEmail('');
    }
  }

  const handleRemoveGuest = (index: number) => {
    const updatedGuests = [...guests];
    const updatedGuestsEmails = [...guestsEmails];

    updatedGuests.splice(index, 1);
    updatedGuestsEmails.splice(index, 1);

    setGuests(updatedGuests);
    setGuestsEmails(updatedGuestsEmails);
  }

  //----------------------------------------------------------------------------------

  return (
    <FormProvider methods={methods} onSubmit={onSubmit}>
      <Stack spacing={3} sx={{ px: 3 }}>
        <RHFTextField name="title" label="Title" />
        <RHFEditor simple name="description" />

        <Controller
          name="start"
          control={control}
          render={({ field }) => (
            <MobileDateTimePicker
              {...field}
              value={field.value ? new Date(field.value) : null}
              onChange={(newValue) => {
                field.onChange(newValue ? newValue.toISOString() : null);
              }}
              label="Start date"
              format="dd/MM/yyyy hh:mm a"
              slotProps={{
                textField: {
                  fullWidth: true,
                  error: !!errors.start,
                  helperText: errors.start?.message,
                },
              }}
            />
          )}
        />

        <Controller
          name="end"
          control={control}
          render={({ field }) => (
            <MobileDateTimePicker
              {...field}
              value={field.value ? new Date(field.value) : null}
              onChange={(newValue) => {
                field.onChange(newValue ? newValue.toISOString() : null);
              }}
              label="End date"
              format="dd/MM/yyyy hh:mm a"
              slotProps={{
                textField: {
                  fullWidth: true,
                  error: !!errors.end,
                  helperText: errors.end?.message,
                },
              }}
            />
          )}
        />

        <RHFSelect
          name="timeZone"
          native={false}
          label="Time Zone"
          fullWidth
          error={!!errors.timeZone}
          helperText={errors.timeZone?.message}
          SelectProps={{
            MenuProps: {
              PaperProps: {
                sx: {
                  maxHeight: 220,
                },
              },
            },
          }}
        >
          <MenuItem value="" disabled>
            Select Time Zone
          </MenuItem>
          {allTimezones.map((option) => (
            <MenuItem key={option.value} value={option.value}>
              {option.label}
            </MenuItem>
          ))}
        </RHFSelect>


        <RHFSelect
          name="notification"
          native={false}
          label="Notification Mode"
          defaultValue={currentEvent?.notification}
          fullWidth
          error={!!errors.notification}
          helperText={errors.notification?.message}
          SelectProps={{
            MenuProps: {
              PaperProps: {
                sx: {
                  maxHeight: 220,
                },
              },
            },
          }}
        >
          <MenuItem>Select Notification Mode</MenuItem>
          <MenuItem value="never">Never</MenuItem>
          <MenuItem value="5">5 minutes before</MenuItem>
          <MenuItem value="10">10 minutes before</MenuItem>
          <MenuItem value="15">15 minutes before</MenuItem>
          <MenuItem value="30">30 minutes before</MenuItem>
          <MenuItem value="60">1 hour before</MenuItem>
        </RHFSelect>

        <RHFSelect
          name="recurring"
          native={false}
          label="Recurring event"
          value={recurring}
          fullWidth
          onChange={handleRecurringOptionChange}
          SelectProps={{
            MenuProps: {
              PaperProps: {
                sx: {
                  maxHeight: 220,
                },
              },
            },
          }}

        >
          <MenuItem value={recurring}>{currentEvent?.recurring?.happens}</MenuItem>
          <MenuItem value="personnaliser">Personnaliser...</MenuItem>
        </RHFSelect>

        {guestsEmails.map((guest, index) => (
          <div key={index} style={{ display: 'flex', alignItems: 'center', width: '100%' }}>
            <TextField
              fullWidth
              disabled
              label={`Guest ${index + 1}`}
              value={guest}
              sx={{ mr: 1 }}
            />
            <IconButton onClick={() => handleRemoveGuest(index)}>
              <Iconify icon="solar:trash-bin-trash-bold" />
            </IconButton>
          </div>
        ))}
        <Button
          onClick={handleOpenDialogUserSearch}
          sx={{
            display: 'flex',
            alignItems: 'center',
            justifyContent: 'flex-start',
          }}
        >
          <Iconify icon="solar:users-group-rounded-bold" sx={{ marginRight: '8px' }} />
          <span>Add Guest</span>
        </Button>

        <Controller
          name="color"
          control={control}
          render={({ field }) => (
            <ColorPicker
              selected={field.value as string}
              onSelectColor={(color) => field.onChange(color as string)}
              colors={colorOptions}
            />
          )}
        />
      </Stack>

      <DialogActions>
        {!!currentEvent?.id && (
          <Tooltip title="Delete Event">
            <IconButton onClick={onDelete}>
              <Iconify icon="solar:trash-bin-trash-bold" />
            </IconButton>
          </Tooltip>
        )}

        <Box sx={{ flexGrow: 1 }} />

        <Button variant="outlined" color="inherit" onClick={onClose}>
          Cancel
        </Button>

        <LoadingButton
          type="submit"
          variant="contained"
          loading={isSubmitting}
          disabled={dateError}
        >
          Save Changes
        </LoadingButton>
      </DialogActions>

      {/**----------------------------------------------------------------------- */}
      <Dialog open={open} onClose={handleCloseDialog}>
        <DialogTitle>Customize Recurrence</DialogTitle>
        <DialogContent>
          <Stack direction="row" marginBottom={1}>
            <Typography variant="subtitle2" sx={{ flexGrow: 1 }}>
              Every
            </Typography>
            <Stack spacing={1}>
              <IncrementerButton
                quantity={every}
                onIncrease={() => handleEveryChange(every + 1)}
                onDecrease={() => handleEveryChange(Math.max(1, every - 1))}
                disabledIncrease={false}
                disabledDecrease={false}
              />
            </Stack>
          </Stack>
          <Stack direction="row" marginBottom={1}>
            <Typography variant="subtitle2" sx={{ flexGrow: 1 }}>
              Happens
            </Typography>
            <RHFSelect
              name="Happens"
              label=""
              size="small"
              value={happens}
              onChange={handleHappensChange}
              sx={{
                maxWidth: 88,
                [`& .${formHelperTextClasses.root}`]: {
                  mx: 0,
                  mt: 1,
                  textAlign: 'right',
                },
              }}
            >
              <MenuItem value="Daily">Daily</MenuItem>
              <MenuItem value="Weekly">Weekly</MenuItem>
              <MenuItem value="Monthly">Monthly</MenuItem>
              <MenuItem value="Yearly">Yearly</MenuItem>

            </RHFSelect>
          </Stack>
          {happens === 'Weekly' && (
            <Stack direction="row" marginBottom={1}>
              <Typography variant="subtitle2" sx={{ flexGrow: 1 }}>
                Days of week
              </Typography>
              <Select
                size="small"
                multiple
                value={selectedDays}
                onChange={handleSelectChange}
                renderValue={(selected) => (
                  <div>
                    {(selected as string[]).map((value) => (
                      <Chip key={value} label={value} />
                    ))}
                  </div>
                )}
              >
                {DAYS_NAME_OPTIONS.map((day) => (
                  <MenuItem key={day.value} value={day.value}>
                    {day.label}
                  </MenuItem>
                ))}
              </Select>
            </Stack>
          )}
          {happens === 'Monthly' && (
            <Stack direction="row" marginBottom={1}>
              <Typography variant="subtitle2" sx={{ flexGrow: 1 }}>
                day of Month
              </Typography>
              <Select
                value={monthlyOption}
                onChange={handleMonthlyOptionChange}
                size="small"
                fullWidth
              >
                <MenuItem value={selectedStartDate ? selectedStartDate.getDate() : 0}>Tous les mois le {selectedStartDate && selectedStartDate.getDate()}</MenuItem>
                <MenuItem value={getDayOfWeek(selectedStartDate)}>Tous les mois le premier {getDayOfWeek(selectedStartDate)}</MenuItem>
              </Select>
            </Stack>
          )}


          <Stack direction="row" marginBottom={1}>
            <Typography variant="subtitle2" sx={{ flexGrow: 1 }}>
              Ends
            </Typography>
            <RHFSelect
              name="Ends"
              label=""
              size="small"
              value={ends}
              onChange={handleEndsChange}
              sx={{
                maxWidth: 88,
                [`& .${formHelperTextClasses.root}`]: {
                  mx: 0,
                  mt: 1,
                  textAlign: 'right',
                },
              }}
            >
              <MenuItem value="ondate">On Date</MenuItem>
            </RHFSelect>
          </Stack>
          {endsOption === 'ondate' && (
            <DatePicker
              label="Select Date"
              value={selectedDate}
              onChange={handleDateChange}
            />
          )}
        </DialogContent>
        <DialogActions>
          <Button onClick={handleCloseDialog}>Cancel</Button>
          <Button onClick={handleSaveDialog} variant="contained" color="primary">Save</Button>
        </DialogActions>
      </Dialog>

      <Dialog open={openUserSearch} onClose={handleCloseDialogUserSearch} fullWidth>
        <DialogTitle>Search for the Guest</DialogTitle>
        <DialogContent>
          <RHFAutocomplete
            name="User"
            label="Guest Email Or Name"
            onInputChange={(e) => handlePutQuery(e)}
            onChange={(event, newValue) => {
              if (newValue) {
                if (typeof newValue === 'object' && 'email' in newValue) {
                  setEmail(newValue.email);
                  setSelectedUserId(newValue.id);
                }
                else if (typeof newValue === 'string') {
                  setEmail(newValue);
                  setSelectedUserId(null);
                }
                else if (Array.isArray(newValue) && newValue.length > 0) {
                  const firstItem = newValue[0];
                  if (typeof firstItem === 'object' && 'email' in firstItem) {
                    setEmail(firstItem.email);
                    setSelectedUserId(firstItem.id);
                  }
                }
              } else {
                setEmail('');
                setSelectedUserId(null);
              }
            }}
            options={users}
            getOptionLabel={(option) => typeof option === 'object' ? option.email : option || ''}
            isOptionEqualToValue={(option, value) => option.id === value.id}
          />
        </DialogContent>
        <DialogActions>
          <Button onClick={handleCloseDialogUserSearch}>Cancel</Button>
          {email && email.length > 0 ?
            <Button onClick={pickUser} variant="contained" color="primary">Invite</Button>
            :
            <Button variant="contained" disabled color="primary">Invite</Button>
          }
        </DialogActions>
      </Dialog>
    </FormProvider>
  );
}
