import { Button, Form } from "@ariakit/react";
import { useState, type Dispatch, type SetStateAction } from "react";
import { Link } from "wouter";
import { useAppConfig, useClient } 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 { button } from "../Letterhead/style.css.ts";
import {
  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 type { AuthEventHandler } from "./types.ts";

type SetStep = Dispatch<SetStateAction<VerifyStep>>;

function InitialStep(props: {
  setStep: SetStep;
  currentUser: CurrentUser;
  reload: () => void;
}) {
  const { setStep, currentUser, reload } = props;
  const { email } = currentUser;
  const { logout } = useAppActions();

  const client = useClient();
  const { form, submitName } = useForm({
    defaultValues: {},
    async onSubmit() {
      const op = await client.requestUserVerification();
      return op.mapFailure(getSubmitFailureMessage);
    },
    onSuccess(value) {
      setStep({ type: "SUBMIT_CODE", tokenId: value.tokenId });
    },
  });

  return (
    <Form store={form}>
      <Letterhead>
        <LetterheadHeader>
          <LetterheadHeading>Verify account</LetterheadHeading>
          <LetterheadParagraph>
            Your account is currently not verified. We will send a one-time code
            to your email ({email}) to complete the verification.
          </LetterheadParagraph>
        </LetterheadHeader>

        <LetterheadFormActions>
          <LetterheadSubmitError name={submitName} />
          <LetterheadSubmitButton>Send code</LetterheadSubmitButton>
          <LetterheadParagraph>
            Cannot complete verification?{" "}
            <Button
              className={interactiveText}
              onClick={async () => {
                await logout();
                reload();
              }}
            >
              Log out
            </Button>
            .
          </LetterheadParagraph>
        </LetterheadFormActions>
      </Letterhead>
    </Form>
  );
}

function SubmitCodeStep(props: {
  tokenId: string;
  setStep: SetStep;
  currentUser: CurrentUser;
}) {
  const client = useClient();
  const { email } = props.currentUser;
  const { form, submitName } = useForm({
    defaultValues: {
      code: "",
    },
    async onSubmit({ values }) {
      const op = await client.verifyUser({
        ...values,
        tokenId: props.tokenId,
      });

      return op.mapFailure((failure) => {
        return getSubmitFailureMessage(failure, {
          404: "🚫 This code is incorrect or expired. Please try again.",
        });
      });
    },
    onSuccess() {
      props.setStep({ type: "SUCCESS" });
    },
  });

  return (
    <Form store={form}>
      <Letterhead>
        <LetterheadHeader>
          <LetterheadHeading>Verify Account</LetterheadHeading>
          <LetterheadParagraph>
            We've sent a one-time code to {email}. Please, enter the code in the
            field below to complete verification.
          </LetterheadParagraph>
        </LetterheadHeader>

        <LetterheadTextField
          name={form.names.code}
          label="Code"
          placeholder="E.g. 123123"
          autoComplete="one-time-code"
          required
        />

        <LetterheadFormActions>
          <LetterheadSubmitError name={submitName} />
          <LetterheadSubmitButton>Verify</LetterheadSubmitButton>
        </LetterheadFormActions>
      </Letterhead>
    </Form>
  );
}

function SuccessStep(props: { onClose?: AuthEventHandler }) {
  const { onClose } = props;
  const { hrefs } = useAppConfig();

  return (
    <Letterhead>
      <LetterheadHeader>
        <LetterheadHeading>Success!</LetterheadHeading>
        <LetterheadParagraph>
          Your Indie Tabletop Club account has been verified. Yay!
        </LetterheadParagraph>
      </LetterheadHeader>

      {onClose ? (
        <Button onClick={() => onClose()} className={button()}>
          Done
        </Button>
      ) : (
        <Link href={hrefs.dashboard()} className={button()}>
          Go to dashboard
        </Link>
      )}
    </Letterhead>
  );
}

type VerifyStep =
  | { type: "INITIAL" }
  | { type: "SUBMIT_CODE"; tokenId: string }
  | { type: "SUCCESS" };

export function VerifyAccountView(props: {
  currentUser: CurrentUser;
  reload: () => void;

  /**
   * If provided, will cause the success step to render a close dialog button
   * instead of "Go to Dashboard" button.
   *
   * This is useful if this view is used within a modal dialog context.
   */
  onClose?: AuthEventHandler;
}) {
  const [step, setStep] = useState<VerifyStep>({ type: "INITIAL" });

  switch (step.type) {
    case "INITIAL": {
      return <InitialStep {...props} setStep={setStep} />;
    }

    case "SUBMIT_CODE": {
      return <SubmitCodeStep {...props} {...step} setStep={setStep} />;
    }

    case "SUCCESS": {
      return <SuccessStep {...props} />;
    }
  }
}
