import type { FormEvent, ReactNode } from "react";
import { Alert, AlertDescription, AlertIcon, Button, Center, FormControl, FormLabel, HStack, Icon, Input, Stack } from "@chakra-ui/react";
import { FcGoogle } from "react-icons/fc";
import type { AuthProviderAvailability, AuthProviderKey, AuthSubmitValues, LoginMode } from "./types";

type LoginFormTexts = {
  nameLabel: string;
  emailLabel: string;
  passwordLabel: string;
  passwordConfirmLabel: string;
  submitRegisterLabel: string;
  submitSignInLabel: string;
  toggleToRegisterLabel: string;
  toggleToSignInLabel: string;
  forgotPasswordLabel: string;
  googleLabel: string;
  slackLabel: string;
};

type LoginFormProps = {
  mode: LoginMode;
  texts: LoginFormTexts;
  onSubmit: (values: AuthSubmitValues) => void | Promise<void>;
  onModeToggle: () => void;
  loading?: boolean;
  oauthLoadingProvider?: AuthProviderKey | null;
  providers?: AuthProviderAvailability;
  onOAuthSignIn?: (provider: AuthProviderKey) => void | Promise<void>;
  errorMessage?: string | null;
  successMessage?: string | null;
  footer?: ReactNode;
  forgotPasswordLink?: ReactNode;
  emailPlaceholder?: string;
  namePlaceholder?: string;
};

export function LoginForm({
  mode,
  texts,
  onSubmit,
  onModeToggle,
  loading = false,
  oauthLoadingProvider = null,
  providers,
  onOAuthSignIn,
  errorMessage,
  successMessage,
  footer,
  forgotPasswordLink,
  emailPlaceholder = "you@example.com",
  namePlaceholder = "Jane Doe"
}: LoginFormProps) {
  const registerMode = mode === "register";

  function handleSubmit(event: FormEvent<HTMLFormElement>) {
    event.preventDefault();
    const form = new FormData(event.currentTarget);
    void onSubmit({
      name: String(form.get("name") ?? ""),
      email: String(form.get("email") ?? ""),
      password: String(form.get("password") ?? ""),
      passwordConfirm: String(form.get("passwordConfirm") ?? "")
    });
  }

  return (
    <Stack spacing={5}>
      {errorMessage ? (
        <Alert status="error" borderRadius="md">
          <AlertIcon />
          <AlertDescription>{errorMessage}</AlertDescription>
        </Alert>
      ) : null}

      {successMessage ? (
        <Alert status="success" borderRadius="md">
          <AlertIcon />
          <AlertDescription>{successMessage}</AlertDescription>
        </Alert>
      ) : null}

      <form onSubmit={handleSubmit}>
        <Stack spacing={4}>
          {registerMode ? (
            <FormControl isRequired>
              <FormLabel>{texts.nameLabel}</FormLabel>
              <Input name="name" placeholder={namePlaceholder} />
            </FormControl>
          ) : null}

          <FormControl isRequired>
            <FormLabel>{texts.emailLabel}</FormLabel>
            <Input name="email" type="email" placeholder={emailPlaceholder} />
          </FormControl>

          <FormControl isRequired>
            <FormLabel>{texts.passwordLabel}</FormLabel>
            <Input name="password" type="password" minLength={8} />
          </FormControl>

          {!registerMode && forgotPasswordLink ? <Stack align="flex-end">{forgotPasswordLink}</Stack> : null}

          {registerMode ? (
            <FormControl isRequired>
              <FormLabel>{texts.passwordConfirmLabel}</FormLabel>
              <Input name="passwordConfirm" type="password" minLength={8} />
            </FormControl>
          ) : null}

          <Button type="submit" isLoading={loading}>
            {registerMode ? texts.submitRegisterLabel : texts.submitSignInLabel}
          </Button>
        </Stack>
      </form>

      {registerMode || !onOAuthSignIn || (!providers?.google && !providers?.slack) ? null : (
        <HStack>
          {providers.google ? (
            <Button
              flex={1}
              bg="gray.200"
              color="gray.900"
              borderRadius="full"
              justifyContent="flex-start"
              h="56px"
              px={3}
              fontSize={{ base: "md", md: "lg" }}
              fontWeight="semibold"
              iconSpacing={4}
              leftIcon={
                <Center boxSize="40px" bg="white" borderRadius="full" boxShadow="sm">
                  <Icon as={FcGoogle} boxSize={6} />
                </Center>
              }
              _hover={{ bg: "gray.300" }}
              _active={{ bg: "gray.300" }}
              isLoading={oauthLoadingProvider === "google"}
              onClick={() => void onOAuthSignIn("google")}
            >
              {texts.googleLabel}
            </Button>
          ) : null}
          {providers.slack ? (
            <Button
              flex={1}
              variant="outline"
              isLoading={oauthLoadingProvider === "slack"}
              onClick={() => void onOAuthSignIn("slack")}
            >
              {texts.slackLabel}
            </Button>
          ) : null}
        </HStack>
      )}

      <Button variant="ghost" onClick={onModeToggle}>
        {registerMode ? texts.toggleToSignInLabel : texts.toggleToRegisterLabel}
      </Button>

      {footer ?? null}
    </Stack>
  );
}
