import React, { useEffect, useState, useRef } from 'react';
import Dialog from '@arcblock/ux/lib/Dialog';
import { useLocaleContext } from '@arcblock/ux/lib/Locale/context';
import { NotificationsOutlined, DateRangeOutlined } from '@mui/icons-material';
import {
  Button,
  CircularProgress,
  Stack,
  Typography,
  FormControl,
  Select,
  MenuItem,
  TextField,
  Box,
  Paper,
  Alert,
  Popper,
  ClickAwayListener,
} from '@mui/material';
import { useRequest } from 'ahooks';
import { FormProvider, useForm, Controller } from 'react-hook-form';
import { useMobile } from '@blocklet/payment-react';
import api from '../../libs/api';

export type NotificationFrequency = 'default' | 'daily' | 'weekly' | 'monthly';

export interface NotificationPreferences {
  notification: {
    frequency: NotificationFrequency;
    schedule?: {
      time: string;
      date?: number;
    };
  };
}

interface NotificationPreferenceDialogProps {
  open: boolean;
  onClose: () => void;
}

const fetchPreferences = async () => {
  const { data } = await api.get('/api/customers/me');
  return data.preference || { notification: { frequency: 'default' } };
};

const updatePreferences = async (preferences: NotificationPreferences) => {
  const { data } = await api.put('/api/customers/preference', preferences);
  return data;
};

const validateTimeFormat = (time: string) => {
  const timeRegex = /^([01]?[0-9]|2[0-3]):[0-5][0-9]$/;
  return timeRegex.test(time);
};

function TimeSelector({
  name,
  control,
  required,
  timeFormatErrorMessage,
}: {
  name: string;
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
  control: any;
  required: boolean;
  timeFormatErrorMessage: string;
}) {
  return (
    <Controller
      name={name}
      control={control}
      rules={{
        required,
        validate: (value) => validateTimeFormat(value) || timeFormatErrorMessage,
      }}
      render={({ field, fieldState }) => (
        <TextField
          type="time"
          size="small"
          sx={{
            minWidth: 'fit-content',
            '& input::-webkit-calendar-picker-indicator': {
              filter: (theme) => (theme.palette.mode === 'dark' ? 'invert(1) brightness(80%)' : 'none'),
            },
          }}
          {...field}
          error={!!fieldState.error}
          helperText={fieldState.error?.message}
        />
      )}
    />
  );
}

function DaySelector({
  value,
  onChange,
  onBlur = () => {},
}: {
  value: number;
  onChange: (day: number) => void;
  onBlur?: () => void;
}) {
  const { t } = useLocaleContext();
  const [open, setOpen] = useState(false);
  const anchorRef = useRef<HTMLButtonElement>(null);

  const handleClickAway = () => {
    setOpen(false);
    onBlur?.();
  };

  return (
    <Box>
      <Button
        ref={anchorRef}
        variant="outlined"
        onClick={() => setOpen(!open)}
        sx={{
          minWidth: 'fit-content',
          display: 'flex',
          alignItems: 'center',
          justifyContent: 'space-between',
          backgroundColor: 'grey.50',
          '&:hover, &:focus': {
            borderColor: 'primary.main',
          },
          color: 'text.secondary',
        }}
        size="large"
        startIcon={<DateRangeOutlined fontSize="small" color="action" sx={{ fontSize: '1rem !important' }} />}
        endIcon={
          <Typography variant="caption" color="action" sx={{ fontSize: '0.75rem !important', lineHeight: 'normal' }}>
            {t('notification.preferences.day')}
          </Typography>
        }>
        {value || 1}
      </Button>

      <Popper
        open={open}
        anchorEl={anchorRef.current}
        placement="bottom-start"
        style={{ zIndex: 1300 }}
        modifiers={[
          {
            name: 'offset',
            options: {
              offset: [0, 8],
            },
          },
        ]}>
        <ClickAwayListener onClickAway={handleClickAway}>
          <Paper
            variant="outlined"
            sx={{
              p: 1,
              borderRadius: 1,
              width: '280px',
              boxShadow: 3,
            }}>
            <Box
              sx={{
                display: 'grid',
                gridTemplateColumns: 'repeat(7, 1fr)',
                gap: 0.5,
              }}>
              {Array.from({ length: 31 }, (_, i) => i + 1).map((day) => (
                <Button
                  key={day}
                  size="small"
                  variant={value === day ? 'contained' : 'text'}
                  onClick={() => {
                    onChange(day);
                    setOpen(false);
                  }}
                  sx={{
                    minWidth: 30,
                    height: 30,
                    p: 0,
                  }}>
                  {day}
                </Button>
              ))}
            </Box>
          </Paper>
        </ClickAwayListener>
      </Popper>
    </Box>
  );
}

export function NotificationPreferenceDialog({ open, onClose }: NotificationPreferenceDialogProps) {
  const { t } = useLocaleContext();
  const [selectedDate, setSelectedDate] = useState<number>(1);

  const { data, loading } = useRequest(fetchPreferences, {
    manual: false,
    refreshDeps: [open],
  });

  const methods = useForm<NotificationPreferences>({
    mode: 'onChange',
    defaultValues: {
      notification: {
        frequency: 'default',
        schedule: {
          time: '10:00',
          date: 1,
        },
      },
    },
  });

  const {
    handleSubmit,
    watch,
    reset,
    control,
    setValue,
    formState: { isValid },
  } = methods;

  const frequency = watch('notification.frequency');
  const dateValue = watch('notification.schedule.date');
  const needsSchedule = frequency !== 'default';

  useEffect(() => {
    if (data && open) {
      reset(data);
      if (data.notification?.schedule?.date) {
        setSelectedDate(data.notification.schedule.date);
      }
    }
  }, [data, reset, open]);

  useEffect(() => {
    if (dateValue) {
      setSelectedDate(dateValue);
    }
  }, [dateValue]);

  const { loading: updating, runAsync: runUpdate } = useRequest(updatePreferences, {
    manual: true,
    onSuccess: () => {
      onClose();
    },
  });

  const onSubmit = (formData: NotificationPreferences) => {
    runUpdate(formData);
  };

  const handleMonthDaySelect = (day: number) => {
    setValue('notification.schedule.date', day, { shouldValidate: true });
    setSelectedDate(day);
  };

  const getDayName = (dayIndex: number) => {
    const days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'];
    return t(`common.days.${days[dayIndex]}`);
  };

  const handleFrequencyChange = (event: React.ChangeEvent<HTMLInputElement> | any) => {
    setValue('notification.frequency', event.target.value as NotificationFrequency);
  };

  return (
    <Dialog
      open={open}
      onClose={onClose}
      disableEscapeKeyDown
      title={
        <Stack
          direction="row"
          spacing={1}
          sx={{
            alignItems: 'center',
          }}>
          <NotificationsOutlined fontSize="small" />
          <Typography variant="h6" component="span">
            {t('notification.preferences.title')}
          </Typography>
        </Stack>
      }
      maxWidth="sm"
      fullWidth
      className="base-dialog"
      actions={
        <Stack direction="row" spacing={2}>
          <Button variant="outlined" color="inherit" onClick={onClose}>
            {t('common.cancel')}
          </Button>
          <Button
            variant="contained"
            color="primary"
            disabled={loading || updating || !isValid}
            onClick={handleSubmit(onSubmit)}>
            {updating && <CircularProgress size={20} sx={{ mr: 1 }} />}
            {t('common.save')}
          </Button>
        </Stack>
      }>
      {loading ? (
        <Stack
          sx={{
            alignItems: 'center',
            justifyContent: 'center',
            height: 200,
          }}>
          <CircularProgress />
        </Stack>
      ) : (
        <FormProvider {...methods}>
          <Box>
            <Alert severity="info">{t('notification.preferences.subscriptionRenewalNote')}</Alert>
            <Typography id="frequency-label" sx={{ color: 'text.primary', mt: 2, mb: 1 }}>
              {t('notification.preferences.frequency.label')}
            </Typography>
            <Stack
              sx={{
                flexDirection: 'row',
              }}>
              <Box
                sx={{
                  display: 'flex',
                  alignItems: 'center',
                  flexWrap: 'nowrap',
                  gap: { xs: 0.5, sm: 1, md: 2 },
                  width: '100%',
                  overflow: 'auto',
                  pb: 1,
                }}>
                <FormControl sx={{ width: { xs: '100px', sm: '120px' }, minWidth: 'fit-content' }}>
                  <Select
                    value={frequency}
                    onChange={handleFrequencyChange}
                    size="small"
                    displayEmpty
                    sx={{
                      fontSize: { xs: '0.85rem', sm: '0.9rem' },
                    }}>
                    <MenuItem value="default">{t('notification.preferences.frequency.default')}</MenuItem>
                    <MenuItem value="daily">{t('notification.preferences.frequency.daily')}</MenuItem>
                    <MenuItem value="weekly">{t('notification.preferences.frequency.weekly')}</MenuItem>
                    <MenuItem value="monthly">{t('notification.preferences.frequency.monthly')}</MenuItem>
                  </Select>
                </FormControl>

                {frequency !== 'default' && (
                  <>
                    {frequency === 'weekly' && (
                      <Controller
                        name="notification.schedule.date"
                        control={control}
                        render={({ field }) => (
                          <Select size="small" sx={{ minWidth: 120 }} value={field.value} onChange={field.onChange}>
                            {[0, 1, 2, 3, 4, 5, 6].map((day) => (
                              <MenuItem key={day} value={day}>
                                {getDayName(day)}
                              </MenuItem>
                            ))}
                          </Select>
                        )}
                      />
                    )}

                    {frequency === 'monthly' && <DaySelector value={dateValue || 1} onChange={handleMonthDaySelect} />}

                    <TimeSelector
                      name="notification.schedule.time"
                      control={control}
                      required={needsSchedule}
                      timeFormatErrorMessage={t('notification.preferences.timeFormatError')}
                    />
                  </>
                )}
              </Box>
            </Stack>
            {selectedDate > 28 && frequency === 'monthly' && (
              <Typography
                variant="caption"
                sx={{
                  color: 'text.secondary',
                  fontStyle: 'italic',
                  display: 'flex',
                  alignItems: 'center',
                  gap: 0.5,
                }}>
                <Box component="span" sx={{ fontSize: '0.8rem' }}>
                  ⚠️
                </Box>
                {t('notification.preferences.monthlyHelp')}
              </Typography>
            )}
          </Box>
        </FormProvider>
      )}
    </Dialog>
  );
}

export default function NotificationPreference() {
  const { t } = useLocaleContext();
  const { isMobile } = useMobile();
  const [open, setOpen] = React.useState(false);

  return (
    <>
      {isMobile ? (
        <Button
          size="small"
          variant="outlined"
          sx={{
            minWidth: 0,
            width: 32,
            height: 32,
            borderRadius: '50%',
          }}
          onClick={() => setOpen(true)}>
          <NotificationsOutlined fontSize="small" />
        </Button>
      ) : (
        <Button
          startIcon={<NotificationsOutlined />}
          size="small"
          onClick={() => setOpen(true)}
          variant="outlined"
          sx={{
            whiteSpace: 'nowrap',
          }}>
          {t('notification.preferences.button')}
        </Button>
      )}
      <NotificationPreferenceDialog open={open} onClose={() => setOpen(false)} />
    </>
  );
}
