import { AuthCardShell, AuthInfoBanner } from "@xtablo/auth-ui";
import { useSession } from "@xtablo/shared/contexts/SessionContext";
import { Button } from "@xtablo/ui/components/button";
import { Input } from "@xtablo/ui/components/input";
import { Label } from "@xtablo/ui/components/label";
import { useEffect, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { useNavigate, useSearchParams } from "react-router-dom";
import { supabase } from "../lib/supabase";

type InviteDetails = {
  email: string;
  tabloId: string;
};

type InviteState = "loading" | "ready" | "invalid";

function getApiUrl() {
  return import.meta.env.VITE_API_URL ?? "";
}

async function parseError(response: Response) {
  const body = (await response.json().catch(() => ({}))) as { error?: string; message?: string };
  return body.error ?? body.message ?? "Une erreur est survenue.";
}

export function SetPasswordPage() {
  const { t } = useTranslation("auth");
  const { session } = useSession();
  const navigate = useNavigate();
  const [searchParams] = useSearchParams();
  const token = searchParams.get("token");
  const [inviteState, setInviteState] = useState<InviteState>(token ? "loading" : "ready");
  const [inviteDetails, setInviteDetails] = useState<InviteDetails | null>(null);
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");
  const [error, setError] = useState<string | null>(null);
  const [isPending, setIsPending] = useState(false);

  const isInviteFlow = Boolean(token);
  const description = useMemo(
    () =>
      isInviteFlow
        ? "Définissez votre mot de passe pour accéder à votre espace client."
        : t("updatePassword.description"),
    [isInviteFlow, t]
  );

  useEffect(() => {
    if (!token) {
      return;
    }

    let isMounted = true;

    fetch(`${getApiUrl()}/api/v1/client-invites/setup/${token}`)
      .then(async (response) => {
        if (!response.ok) {
          throw new Error(await parseError(response));
        }

        return (await response.json()) as InviteDetails;
      })
      .then((details) => {
        if (!isMounted) return;
        setInviteDetails(details);
        setInviteState("ready");
      })
      .catch((err: unknown) => {
        if (!isMounted) return;
        setError(err instanceof Error ? err.message : "Lien invalide");
        setInviteState("invalid");
      });

    return () => {
      isMounted = false;
    };
  }, [token]);

  const onSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setError(null);

    if (password.length < 8) {
      setError(t("signup.errors.passwordLength"));
      return;
    }

    if (password !== confirmPassword) {
      setError(t("signup.errors.passwordMatch"));
      return;
    }

    setIsPending(true);

    try {
      if (token && inviteDetails) {
        const response = await fetch(`${getApiUrl()}/api/v1/client-invites/setup/${token}`, {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify({ password }),
        });

        if (!response.ok) {
          throw new Error(await parseError(response));
        }

        const result = (await response.json()) as InviteDetails & { success: boolean };
        const { error: signInError } = await supabase.auth.signInWithPassword({
          email: result.email,
          password,
        });

        if (signInError) {
          throw signInError;
        }

        navigate(`/tablo/${result.tabloId}`);
        return;
      }

      const { error: updateError } = await supabase.auth.updateUser({ password });
      if (updateError) {
        throw updateError;
      }

      navigate("/login");
    } catch (err) {
      setError(err instanceof Error ? err.message : "Une erreur est survenue.");
    } finally {
      setIsPending(false);
    }
  };

  if (inviteState === "loading") {
    return (
      <AuthCardShell title="Définir votre mot de passe" description={description}>
        <div className="flex justify-center py-8">
          <div className="h-8 w-8 animate-spin rounded-full border-b-2 border-primary" />
        </div>
      </AuthCardShell>
    );
  }

  if (inviteState === "invalid") {
    return (
      <AuthCardShell title="Lien invalide" description="Ce lien ne peut plus être utilisé.">
        <AuthInfoBanner message={error ?? "Lien invalide"} variant="error" />
      </AuthCardShell>
    );
  }

  const shouldShowRecoveryHint = !isInviteFlow && !session;

  return (
    <AuthCardShell
      title={isInviteFlow ? "Définir votre mot de passe" : t("updatePassword.title")}
      description={description}
    >
      <div className="space-y-6">
        {error ? <AuthInfoBanner message={error} variant="error" /> : null}
        {shouldShowRecoveryHint ? (
          <AuthInfoBanner
            message="Utilisez le lien reçu par email pour définir ou réinitialiser votre mot de passe."
            variant="info"
          />
        ) : null}

        <form className="space-y-4" onSubmit={onSubmit}>
          <div className="space-y-2">
            <Label htmlFor="password">Mot de passe</Label>
            <Input
              id="password"
              name="password"
              type="password"
              value={password}
              onChange={(event) => setPassword(event.target.value)}
              required
              disabled={isPending}
            />
          </div>

          <div className="space-y-2">
            <Label htmlFor="confirmPassword">Confirmer le mot de passe</Label>
            <Input
              id="confirmPassword"
              name="confirmPassword"
              type="password"
              value={confirmPassword}
              onChange={(event) => setConfirmPassword(event.target.value)}
              required
              disabled={isPending}
            />
          </div>

          <Button className="w-full" type="submit" disabled={isPending}>
            Définir mon mot de passe
          </Button>
        </form>
      </div>
    </AuthCardShell>
  );
}
