import { Button, Form, useStoreState } from "@ariakit/react";
import type { ReactNode } from "react";
import { Link, useLocation, useSearchParams } from "wouter";
import { useAppConfig } from "../AppConfig/AppConfig.tsx";
import { interactiveText } from "../common.css.ts";
import { getSubmitFailureMessage } from "../failureMessages.ts";
import {
  Letterhead,
  LetterheadHeading,
  LetterheadParagraph,
  LetterheadSubmitButton,
} from "../Letterhead/index.tsx";
import {
  InputsStack,
  LetterheadFormActions,
  LetterheadHeader,
  LetterheadSubmitError,
  LetterheadTextField,
} from "../LetterheadForm/index.tsx";
import { useAppActions } from "../store/index.tsx";
import type { CurrentUser } from "../types.ts";
import { useForm } from "../use-form.ts";
import { validEmail } from "../validations.ts";
import type { AuthEventHandler, DefaultFormValues } from "./types.ts";
import { useRedirectPath } from "./useRedirectPath.ts";

export function LoginView(props: {
  defaultValues?: DefaultFormValues;
  onLogin?: AuthEventHandler;
  currentUser: CurrentUser | null;
  description: ReactNode;
  reload: () => void;
}) {
  const [params] = useSearchParams();
  const { currentUser, defaultValues, description, onLogin, reload } = props;
  const { placeholders, client, hrefs } = useAppConfig();
  const { logout } = useAppActions();

  const localUserPresent = !!currentUser?.email;
  const defaultEmailValue = currentUser?.email ?? defaultValues?.email ?? "";
  const redirectPath = useRedirectPath() ?? hrefs.dashboard();
  const [_, navigate] = useLocation();

  const { form, submitName } = useForm({
    defaultValues: { email: defaultEmailValue, password: "" },
    validate: { email: validEmail },
    async onSubmit({ values }) {
      const result = await client.login(values);

      return result.mapFailure((failure) => {
        return getSubmitFailureMessage(failure, {
          401: "🔐 Username and password do not match.",
          404: "🤔 Couldn't find a user with this email address.",
        });
      });
    },
    onSuccess() {
      if (onLogin) {
        onLogin();
      }

      // If a custom onLogin handler is not provided, will automatically
      // navigate to the appropriate redirect path.
      else {
        navigate(redirectPath);
      }
    },
  });

  const emailValue = useStoreState(form, (state) => state.values.email);

  return (
    <Letterhead>
      <LetterheadHeader>
        <LetterheadHeading>Log in</LetterheadHeading>

        {localUserPresent ?
          <>
            <LetterheadParagraph>
              Your session has expired. Please log into Indie Tabletop Club
              again.
            </LetterheadParagraph>

            <LetterheadParagraph>
              {"To use a different account, please "}
              <Button
                className={interactiveText}
                onClick={async () => {
                  await logout();
                  reload();
                }}
              >
                log out
              </Button>
              {" first."}
            </LetterheadParagraph>
          </>
        : <LetterheadParagraph>
            {description}
            {" Do not have an account? "}
            <Link
              href={hrefs.join({
                redirectTo: params.get("redirectTo") ?? undefined,
                backTo: params.get("backTo") ?? undefined,
              })}
              className={interactiveText}
              state={{ emailValue }}
            >
              Join now
            </Link>
            {"."}
          </LetterheadParagraph>
        }
      </LetterheadHeader>

      <Form store={form} resetOnSubmit={false}>
        <InputsStack>
          <LetterheadTextField
            name={form.names.email}
            placeholder={placeholders.email}
            label="Email"
            type="email"
            readOnly={localUserPresent}
            required
          />
          <LetterheadTextField
            name={form.names.password}
            label="Password"
            placeholder="Your password"
            type="password"
            required
          />
        </InputsStack>

        <LetterheadFormActions>
          <LetterheadSubmitError name={submitName} />
          <LetterheadSubmitButton>Log in</LetterheadSubmitButton>

          <LetterheadParagraph align="start">
            Forgot password?{" "}
            <Link
              href="/password"
              className={interactiveText}
              state={{ emailValue }}
            >
              Reset it
            </Link>
            {"."}
          </LetterheadParagraph>
        </LetterheadFormActions>
      </Form>
    </Letterhead>
  );
}
