import { useEffect, useState } from "react";
import type { SubmitEvent } from "react";
import { Link, useNavigate, useSearchParams } from "react-router";
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro";

import { API_URL, VALIDATION } from "../config/api.ts";
import {
  deserializeAuthResponse,
  parseAPIResponse,
  type RawAuthResponse,
  type RegisterRequest,
} from "../model.ts";
import { useAuth } from "../hooks/useAuth.ts";
import { PageShell } from "../components/PageShell.tsx";
import { ErrorCard } from "../components/ErrorCard.tsx";
import { friendlyFetchError } from "../utils/apiError.ts";

type TokenState =
  | { status: "checking" }
  | { status: "invalid" }
  | { status: "valid" };

type FormState =
  | { status: "idle" }
  | { status: "submitting" }
  | { status: "error"; error: string };

export function UserRegister() {
  const navigate = useNavigate();
  const { login } = useAuth();
  const [searchParams] = useSearchParams();
  const token = searchParams.get("token") ?? "";

  const [tokenState, setTokenState] = useState<TokenState>(() =>
    token ? { status: "checking" } : { status: "invalid" }
  );
  const [formState, setFormState] = useState<FormState>({ status: "idle" });
  const [prevToken, setPrevToken] = useState(token);

  if (prevToken !== token) {
    setPrevToken(token);
    setTokenState(token ? { status: "checking" } : { status: "invalid" });
  }

  useEffect(() => {
    if (!token) return;
    fetch(`${API_URL}/api/invites/${encodeURIComponent(token)}`)
      .then((r) => {
        setTokenState(r.ok ? { status: "valid" } : { status: "invalid" });
      })
      .catch(() => setTokenState({ status: "invalid" }));
  }, [token]);

  const handleSubmit = async (e: SubmitEvent<HTMLFormElement>) => {
    e.preventDefault();
    setFormState({ status: "submitting" });

    const formData = new FormData(e.currentTarget);
    const username = formData.get("username") as string;
    const password = formData.get("password") as string;
    const email = formData.get("email") as string;

    try {
      const res = await fetch(`${API_URL}/api/users/register`, {
        method: "POST",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify(
          {
            username,
            password,
            inviteToken: token,
            email,
          } satisfies RegisterRequest,
        ),
      });

      const apiResponse = parseAPIResponse<RawAuthResponse>(await res.json());

      if (apiResponse.success) {
        login(deserializeAuthResponse(apiResponse.data));
        navigate("/");
      } else {
        setFormState({ status: "error", error: apiResponse.error.message });
      }
    } catch (err) {
      setFormState({ status: "error", error: friendlyFetchError(err) });
    }
  };

  if (tokenState.status === "checking") {
    return (
      <PageShell centered>
        <p className="page-loading"><Trans>Checking invite…</Trans></p>
      </PageShell>
    );
  }

  if (tokenState.status === "invalid") {
    return (
      <PageShell centered>
        <div className="page-error-wrap">
          <ErrorCard
            title={t`Invalid invite`}
            message={t`This invite link is missing, expired, or already used.`}
          />
        </div>
      </PageShell>
    );
  }

  return (
    <PageShell centered>
      <div className="auth-card">
        <h1 className="auth-card-title"><Trans>Register</Trans></h1>

        {formState.status === "error" && (
          <ErrorCard title={t`Registration failed`} message={formState.error} />
        )}

        <form onSubmit={handleSubmit} className="auth-form">
          <input
            name="username"
            type="text"
            placeholder={t`Username`}
            required
            pattern={`[a-zA-Z0-9_]{${VALIDATION.USERNAME_MIN},${VALIDATION.USERNAME_MAX}}`}
            title={t`${VALIDATION.USERNAME_MIN}–${VALIDATION.USERNAME_MAX} characters: letters, numbers, or underscores`}
            disabled={formState.status === "submitting"}
            autoFocus
          />
          <input
            name="email"
            type="email"
            placeholder={t`Email address`}
            required
            disabled={formState.status === "submitting"}
          />
          <input
            name="password"
            type="password"
            placeholder={t`Password (min. ${VALIDATION.PASSWORD_MIN} characters)`}
            required
            minLength={VALIDATION.PASSWORD_MIN}
            maxLength={VALIDATION.PASSWORD_MAX}
            disabled={formState.status === "submitting"}
          />
          <button
            type="submit"
            className="btn-primary"
            disabled={formState.status === "submitting"}
          >
            {formState.status === "submitting"
              ? <Trans>Registering…</Trans>
              : <Trans>Register</Trans>}
          </button>
        </form>

        <p className="auth-card-footer">
          <Trans>Already have an account? <Link to="/login">Log in</Link></Trans>
        </p>
      </div>
    </PageShell>
  );
}
