import React, { useEffect, useState } from "react";

import {
  Autocomplete,
  Box,
  Button,
  Chip,
  Dialog,
  DialogActions,
  DialogContent,
  DialogTitle,
  TextField,
} from "@mui/material";

import { useSnackbar } from "notistack";

import { useApi } from "../../../contexts/ApiContext";
import { useI18n } from "../../../contexts/I18nContext";
import { PageProps } from "../../../types";
import { GroupOption, StaffOptions } from "../types/staff";

export interface InviteUserModalProps {
  open: boolean;
  setOpen: (open: boolean) => void;
  refresh: PageProps["refresh"];
}

export const InviteUserModal: React.FC<InviteUserModalProps> = ({ open, setOpen, refresh }) => {
  const { t } = useI18n();
  const api = useApi();
  const { enqueueSnackbar } = useSnackbar();

  const [email, setEmail] = useState("");
  const [selectedGroups, setSelectedGroups] = useState<GroupOption[]>([]);
  const [availableGroups, setAvailableGroups] = useState<GroupOption[]>([]);
  const [loading, setLoading] = useState(false);
  const [emailError, setEmailError] = useState("");

  useEffect(() => {
    const fetchOptions = async () => {
      const response = await api.operations["user.staff:options"].call({});
      if (response.ok) {
        const options: StaffOptions = await response.json();
        setAvailableGroups(options.groups);
      }
    };
    if (open) {
      fetchOptions();
    }
  }, [api, open]);

  const handleClose = () => {
    setEmail("");
    setSelectedGroups([]);
    setEmailError("");
    setOpen(false);
  };

  const validateEmail = (email: string): boolean => {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  };

  const handleSubmit = async () => {
    // Validate email
    if (!email) {
      setEmailError(t("Email is required"));
      return;
    }

    if (!validateEmail(email)) {
      setEmailError(t("Please enter a valid email address"));
      return;
    }

    if (selectedGroups.length === 0) {
      enqueueSnackbar(t("Please select at least one group"), { variant: "error" });
      return;
    }

    setLoading(true);
    setEmailError("");

    try {
      const response = await api.operations["user.staff:invite"].call({
        body: {
          email,
          groups: selectedGroups.map((g) => g.id),
        },
      });

      if (response.ok) {
        const data = await response.json();
        enqueueSnackbar(data.message || t("Invite sent successfully"), { variant: "success" });
        handleClose();
        refresh();
      } else {
        const errorData = await response.json();
        if (errorData.detail && Array.isArray(errorData.detail)) {
          const emailErrors = errorData.detail.filter((err: { loc?: string[]; msg?: string }) =>
            err.loc?.includes("email"),
          );
          if (emailErrors.length > 0) {
            setEmailError(emailErrors[0].msg);
          } else {
            enqueueSnackbar(errorData.detail[0]?.msg || t("Failed to send invite"), {
              variant: "error",
            });
          }
        } else {
          enqueueSnackbar(t("Failed to send invite"), { variant: "error" });
        }
      }
    } catch (error) {
      console.error("[INVITE_USER]", error);
      enqueueSnackbar(t("Failed to send invite"), { variant: "error" });
    } finally {
      setLoading(false);
    }
  };

  return (
    <Dialog open={open} sx={{ "& .MuiPaper-rounded": { borderRadius: 3 } }} onClose={handleClose}>
      <DialogTitle sx={{ p: 3 }}>{t("Invite Staff User")}</DialogTitle>
      <DialogContent sx={{ p: 3, minWidth: 500 }}>
        <Box display="flex" flexDirection="column" gap={3}>
          <TextField
            fullWidth
            error={!!emailError}
            helperText={emailError || t("Enter the email address of the user to invite")}
            label={t("Email")}
            type="email"
            value={email}
            onChange={(e) => {
              setEmail(e.target.value);
              setEmailError("");
            }}
          />

          <Autocomplete
            fullWidth
            multiple
            getOptionLabel={(option) => option.name}
            isOptionEqualToValue={(option, value) => option.id === value.id}
            options={availableGroups}
            renderInput={(params) => (
              <TextField
                {...params}
                helperText={t("Select one or more groups for the user")}
                label={t("Groups")}
              />
            )}
            renderTags={(value, getTagProps) =>
              value.map((option, index) => (
                <Chip
                  {...getTagProps({ index })}
                  key={option.id}
                  label={option.name}
                  size="small"
                />
              ))
            }
            size="small"
            value={selectedGroups}
            onChange={(_, newValue) => setSelectedGroups(newValue)}
          />
        </Box>
      </DialogContent>
      <DialogActions sx={{ px: 3, py: 3 }}>
        <Button onClick={handleClose}>{t("Cancel")}</Button>
        <Button disabled={loading} variant="contained" onClick={handleSubmit}>
          {loading ? t("Sending...") : t("Send Invite")}
        </Button>
      </DialogActions>
    </Dialog>
  );
};

export default InviteUserModal;
