import { useEffect, useMemo, useState } from "react";
import { isAxiosError } from "axios";
import { useTranslation } from "react-i18next";
import {
  ActionIcon,
  Button,
  Checkbox,
  CloseButton,
  Group,
  Modal,
  PasswordInput,
  Stack,
  Text,
  Tooltip,
} from "@mantine/core";
import LocalIcon from "@app/components/shared/LocalIcon";
import { alert } from "@app/components/toast";
import {
  ChangeUserPasswordRequest,
  User,
  userManagementService,
} from "@app/services/userManagementService";
import { Z_INDEX_OVER_CONFIG_MODAL } from "@app/styles/zIndex";

interface ChangeUserPasswordModalProps {
  opened: boolean;
  onClose: () => void;
  user: User | null;
  onSuccess: () => void;
  mailEnabled: boolean;
}

function generateSecurePassword() {
  const charset =
    "ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz0123456789@$!%*?&";
  const length = 14;
  let password = "";
  const charsetLength = charset.length;
  const uint8Array = new Uint8Array(length);
  window.crypto.getRandomValues(uint8Array);
  // To avoid modulo bias, discard values >= 256 - (256 % charsetLength)
  for (let i = 0; password.length < length; ) {
    const randomByte = uint8Array[i];
    i++;
    if (randomByte >= Math.floor(256 / charsetLength) * charsetLength) {
      // Discard and generate a new random value
      if (i >= uint8Array.length) {
        // Exhausted the array, fill a new one
        window.crypto.getRandomValues(uint8Array);
        i = 0;
      }
      continue;
    }
    const randomIndex = randomByte % charsetLength;
    password += charset[randomIndex];
  }
  return password;
}

export default function ChangeUserPasswordModal({
  opened,
  onClose,
  user,
  onSuccess,
  mailEnabled,
}: ChangeUserPasswordModalProps) {
  const { t } = useTranslation();
  const [form, setForm] = useState({
    newPassword: "",
    confirmPassword: "",
    generateRandom: false,
    sendEmail: false,
    includePassword: false,
    forcePasswordChange: false,
  });
  const [processing, setProcessing] = useState(false);

  const disabled = !user;

  const handleGeneratePassword = () => {
    const generated = generateSecurePassword();
    setForm((prev) => ({
      ...prev,
      newPassword: generated,
      confirmPassword: generated,
      generateRandom: true,
    }));
  };

  const handleCopyPassword = async () => {
    if (!form.newPassword) return;
    try {
      await navigator.clipboard.writeText(form.newPassword);
      alert({
        alertType: "success",
        title: t(
          "workspace.people.changePassword.copiedToClipboard",
          "Password copied to clipboard",
        ),
      });
    } catch (_error) {
      alert({
        alertType: "error",
        title: t(
          "workspace.people.changePassword.copyFailed",
          "Failed to copy password",
        ),
      });
    }
  };

  const resetState = () => {
    setForm({
      newPassword: "",
      confirmPassword: "",
      generateRandom: false,
      sendEmail: false,
      includePassword: false,
      forcePasswordChange: false,
    });
  };

  const handleClose = () => {
    if (processing) return;
    resetState();
    onClose();
  };

  const handleSubmit = async () => {
    if (!user) return;

    if (!form.generateRandom && !form.newPassword.trim()) {
      alert({
        alertType: "error",
        title: t(
          "workspace.people.changePassword.passwordRequired",
          "Please enter a new password",
        ),
      });
      return;
    }

    if (!form.generateRandom && form.newPassword !== form.confirmPassword) {
      alert({
        alertType: "error",
        title: t(
          "workspace.people.changePassword.passwordMismatch",
          "Passwords do not match",
        ),
      });
      return;
    }

    const payload: ChangeUserPasswordRequest = {
      username: user.username,
      newPassword: form.newPassword, // Always send the password (frontend generates it when generateRandom is true)
      generateRandom: false, // Not needed since we're generating on frontend
      sendEmail: form.sendEmail,
      includePassword: form.includePassword,
      forcePasswordChange: form.forcePasswordChange,
    };

    try {
      setProcessing(true);
      await userManagementService.changeUserPassword(payload);
      alert({
        alertType: "success",
        title: t(
          "workspace.people.changePassword.success",
          "Password updated successfully",
        ),
      });
      onSuccess();
      handleClose();
    } catch (error: unknown) {
      const errorMessage = isAxiosError(error)
        ? error.response?.data?.message ||
          error.response?.data?.error ||
          error.message
        : (error instanceof Error ? error.message : undefined) ||
          t(
            "workspace.people.changePassword.error",
            "Failed to update password",
          );
      alert({ alertType: "error", title: errorMessage });
    } finally {
      setProcessing(false);
    }
  };

  useEffect(() => {
    if (opened) {
      setForm({
        newPassword: "",
        confirmPassword: "",
        generateRandom: false,
        sendEmail: false,
        includePassword: false,
        forcePasswordChange: false,
      });
    }
  }, [opened, user?.username]);

  // Check if username is a valid email format
  const isValidEmail = (email: string | undefined) => {
    if (!email) return false;
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  };

  const canEmail = mailEnabled && isValidEmail(user?.username);
  const passwordPreview = useMemo(
    () => (form.newPassword && form.generateRandom ? form.newPassword : ""),
    [form.generateRandom, form.newPassword],
  );

  return (
    <Modal
      opened={opened}
      onClose={handleClose}
      size="md"
      zIndex={Z_INDEX_OVER_CONFIG_MODAL}
      centered
      padding="xl"
      withCloseButton={false}
    >
      <div style={{ position: "relative" }}>
        <CloseButton
          onClick={handleClose}
          size="lg"
          disabled={processing}
          style={{
            position: "absolute",
            top: -8,
            right: -8,
            zIndex: 1,
          }}
        />
        <Stack gap="lg" pt="md">
          <Stack gap="md" align="center">
            <LocalIcon
              icon="lock"
              width="3rem"
              height="3rem"
              style={{ color: "var(--mantine-color-gray-6)" }}
            />
            <Text size="xl" fw={600} ta="center">
              {t("workspace.people.changePassword.title", "Change password")}
            </Text>
            <Text size="sm" c="dimmed" ta="center">
              {t(
                "workspace.people.changePassword.subtitle",
                "Update the password for",
              )}{" "}
              <strong>{user?.username}</strong>
            </Text>
          </Stack>

          <Stack gap="sm">
            <PasswordInput
              label={t(
                "workspace.people.changePassword.newPassword",
                "New password",
              )}
              placeholder={t(
                "workspace.people.changePassword.placeholder",
                "Enter a new password",
              )}
              value={form.newPassword}
              onChange={(event) =>
                setForm({
                  ...form,
                  newPassword: event.currentTarget.value,
                  generateRandom: false,
                })
              }
              disabled={processing || disabled || form.generateRandom}
              data-autofocus
            />
            <PasswordInput
              label={t(
                "workspace.people.changePassword.confirmPassword",
                "Confirm password",
              )}
              placeholder={t(
                "workspace.people.changePassword.confirmPlaceholder",
                "Re-enter the new password",
              )}
              value={form.confirmPassword}
              onChange={(event) =>
                setForm({
                  ...form,
                  confirmPassword: event.currentTarget.value,
                  generateRandom: false,
                })
              }
              disabled={processing || disabled || form.generateRandom}
              error={
                !form.generateRandom &&
                form.confirmPassword &&
                form.newPassword !== form.confirmPassword
                  ? t(
                      "workspace.people.changePassword.passwordMismatch",
                      "Passwords do not match",
                    )
                  : undefined
              }
            />
            <Group justify="space-between">
              <Checkbox
                label={t(
                  "workspace.people.changePassword.generateRandom",
                  "Generate secure password",
                )}
                checked={form.generateRandom}
                disabled={processing || disabled}
                onChange={(event) => {
                  const checked = event.currentTarget.checked;
                  setForm((prev) => ({ ...prev, generateRandom: checked }));
                  if (event.currentTarget.checked) {
                    handleGeneratePassword();
                  }
                }}
              />
              {passwordPreview && (
                <Group gap="xs" align="center">
                  <Text size="xs" c="dimmed">
                    {t(
                      "workspace.people.changePassword.generatedPreview",
                      "Generated password:",
                    )}{" "}
                    <strong>{passwordPreview}</strong>
                  </Text>
                  <Tooltip
                    label={t(
                      "workspace.people.changePassword.copyTooltip",
                      "Copy to clipboard",
                    )}
                  >
                    <ActionIcon
                      size="sm"
                      variant="subtle"
                      color="gray"
                      onClick={handleCopyPassword}
                      disabled={processing}
                    >
                      <LocalIcon
                        icon="content-copy"
                        width="0.9rem"
                        height="0.9rem"
                      />
                    </ActionIcon>
                  </Tooltip>
                </Group>
              )}
            </Group>
          </Stack>

          <Stack gap="xs">
            <Checkbox
              label={t(
                "workspace.people.changePassword.sendEmail",
                "Email the user about this change",
              )}
              checked={canEmail && form.sendEmail}
              onChange={(event) =>
                setForm({ ...form, sendEmail: event.currentTarget.checked })
              }
              disabled={!canEmail || processing}
            />
            <Checkbox
              label={t(
                "workspace.people.changePassword.includePassword",
                "Include the new password in the email",
              )}
              checked={canEmail && form.sendEmail && form.includePassword}
              onChange={(event) =>
                setForm({
                  ...form,
                  includePassword: event.currentTarget.checked,
                })
              }
              disabled={!canEmail || !form.sendEmail || processing}
            />
            <Checkbox
              label={t(
                "workspace.people.changePassword.forcePasswordChange",
                "Force user to change password on next login",
              )}
              checked={form.forcePasswordChange}
              onChange={(event) =>
                setForm({
                  ...form,
                  forcePasswordChange: event.currentTarget.checked,
                })
              }
              disabled={processing || disabled}
            />
            {!canEmail && (
              <Text size="xs" c="dimmed">
                {mailEnabled
                  ? t(
                      "workspace.people.changePassword.emailUnavailable",
                      "This user's email is not a valid email address. Notifications are disabled.",
                    )
                  : t(
                      "workspace.people.changePassword.smtpDisabled",
                      "Email notifications require SMTP to be enabled in settings.",
                    )}
              </Text>
            )}
            {canEmail && !form.includePassword && form.sendEmail && (
              <Text size="xs" c="dimmed">
                {t(
                  "workspace.people.changePassword.notifyOnly",
                  "An email will be sent without the password, letting the user know an admin changed it.",
                )}
              </Text>
            )}
          </Stack>

          <Button
            onClick={handleSubmit}
            loading={processing}
            fullWidth
            size="md"
            disabled={disabled}
            mt="md"
          >
            {t("workspace.people.changePassword.submit", "Update password")}
          </Button>
        </Stack>
      </div>
    </Modal>
  );
}
