import React, { useEffect, useMemo, useState } from "react";
import { usePage } from "@inertiajs/react";
import { useTranslation } from "react-i18next";
import toast from "react-hot-toast";
import { LoaderCircle } from "lucide-react";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import InputError from "@/components/input-error";
import TextLink from "@/components/text-link";

declare const route: (name: string, params?: Record<string, unknown>) => string;

export interface AuthUserPayload {
  id?: number;
  email?: string;
  name?: string | null;
  pending_purchase?: boolean;
}

interface LoginFormProps {
  onSuccess?: (userData: AuthUserPayload | null) => void;
  canResetPassword?: boolean;
  locale?: string;
  packageId?: number | null;
}

type SharedPageProps = {
  locale?: string;
};

type FieldErrors = Record<string, string>;

const metaCsrfToken = () =>
  (document.querySelector('meta[name="csrf-token"]') as HTMLMetaElement | null)?.content ?? "";

const xsrfCookieToken = () => {
  if (typeof document === "undefined") {
    return "";
  }

  const match = document.cookie.match(/(?:^|; )XSRF-TOKEN=([^;]*)/);
  return match ? decodeURIComponent(match[1]) : "";
};

export default function LoginForm({ onSuccess, canResetPassword = true, locale, packageId }: LoginFormProps) {
  const page = usePage<SharedPageProps>();
  const { t } = useTranslation("auth");
  const resolvedLocale = locale ?? page.props.locale ?? "de";

  const loginEndpoint = '/checkout/login';

  const canUseOauth = typeof packageId === "number" && !Number.isNaN(packageId);
  const googleHref = useMemo(() => {
    if (!canUseOauth) {
      return "";
    }

    const params = new URLSearchParams({
      package_id: String(packageId),
      locale: resolvedLocale,
    });

    return `/checkout/auth/google?${params.toString()}`;
  }, [canUseOauth, packageId, resolvedLocale]);

  const facebookHref = useMemo(() => {
    if (!canUseOauth) {
      return "";
    }

    const params = new URLSearchParams({
      package_id: String(packageId),
      locale: resolvedLocale,
    });

    return `/checkout/auth/facebook?${params.toString()}`;
  }, [canUseOauth, packageId, resolvedLocale]);
      
  const [values, setValues] = useState({
    identifier: "",
    password: "",
    remember: false,
  });
  const [errors, setErrors] = useState<FieldErrors>({});
  const [isSubmitting, setIsSubmitting] = useState(false);
  const [isRedirectingToGoogle, setIsRedirectingToGoogle] = useState(false);
  const [isRedirectingToFacebook, setIsRedirectingToFacebook] = useState(false);
  const [hasTriedSubmit, setHasTriedSubmit] = useState(false);
  const [shouldFocusError, setShouldFocusError] = useState(false);

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

    const collected = Object.values(errors).filter(Boolean);
    if (collected.length > 0) {
      toast.error(collected.join(" \u2022 "));
    }
  }, [errors, hasTriedSubmit]);

  useEffect(() => {
    if (!hasTriedSubmit || !shouldFocusError) {
      return;
    }

    const firstKey = Object.keys(errors).find((key) => Boolean(errors[key]));
    if (!firstKey) {
      return;
    }

    const field = document.querySelector<HTMLInputElement>(`[name="${firstKey}"]`);
    field?.scrollIntoView({ behavior: "smooth", block: "center" });
    field?.focus();
    setShouldFocusError(false);
  }, [errors, hasTriedSubmit, shouldFocusError]);

  const updateValue = (key: keyof typeof values, value: string | boolean) => {
    setValues((current) => ({ ...current, [key]: value }));
    setErrors((current) => ({ ...current, [key as string]: "" }));
    setShouldFocusError(false);
  };

  const submit = async (event: React.FormEvent<HTMLFormElement>) => {
    event.preventDefault();
    setHasTriedSubmit(true);
    setErrors({});
    setIsSubmitting(true);

    try {
      const cookieToken = xsrfCookieToken();
      const metaToken = metaCsrfToken();

      const response = await fetch(loginEndpoint, {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
          Accept: "application/json",
          ...(cookieToken
            ? { "X-XSRF-TOKEN": cookieToken }
            : metaToken
              ? { "X-CSRF-TOKEN": metaToken }
              : {}),
        },
        credentials: "same-origin",
        body: JSON.stringify({
          identifier: values.identifier,
          password: values.password,
          remember: values.remember,
          locale: resolvedLocale,
          package_id: packageId ?? null,
        }),
      });

      if (response.ok) {
        const payload = await response.json();
        const nextUser: AuthUserPayload | null = payload?.user ?? payload?.data ?? null;

        toast.success(t("login.success_toast", "Login erfolgreich"));
        onSuccess?.(nextUser);
        setValues((current) => ({ ...current, password: "" }));
        setHasTriedSubmit(false);
        return;
      }

      if (response.status === 422) {
        const payload = await response.json();
        const fieldErrors: FieldErrors = {};
        const source = payload?.errors ?? {};
        Object.entries(source).forEach(([key, message]) => {
          if (Array.isArray(message) && message.length > 0) {
            fieldErrors[key] = String(message[0]);
          } else if (typeof message === "string") {
            fieldErrors[key] = message;
          }
        });

        setErrors(fieldErrors);
        setShouldFocusError(true);
        toast.error(t("login.failed_generic", "Ungueltige Anmeldedaten"));
        return;
      }

      toast.error(t("login.unexpected_error", "Beim Login ist ein Fehler aufgetreten."));
      setShouldFocusError(false);
    } catch (error) {
      console.error("Login request failed", error);
      toast.error(t("login.unexpected_error", "Beim Login ist ein Fehler aufgetreten."));
    } finally {
      setIsSubmitting(false);
    }
  };

  const handleGoogleLogin = () => {
    if (!googleHref) {
      return;
    }

    setIsRedirectingToGoogle(true);
    window.location.href = googleHref;
  };

  const handleFacebookLogin = () => {
    if (!facebookHref) {
      return;
    }

    setIsRedirectingToFacebook(true);
    window.location.href = facebookHref;
  };

  return (
    <form onSubmit={submit} className="flex flex-col gap-6" noValidate>
      <div className="grid gap-6">
        <div className="grid gap-2">
          <Label htmlFor="identifier">{t("login.identifier") || t("login.email")}</Label>
          <Input
            id="identifier"
            type="text"
            name="identifier"
            required
            autoFocus
            placeholder={t("login.identifier_placeholder") || t("login.email_placeholder")}
            value={values.identifier}
            onChange={(event) => updateValue("identifier", event.target.value)}
          />
          <InputError message={errors.identifier || errors.email} />
        </div>
  
        <div className="grid gap-2">
          <div className="flex items-center">
            <Label htmlFor="password">{t("login.password")}</Label>
            {canResetPassword && (
              <TextLink href={typeof route === "function" ? route("password.request") : "/forgot-password"} className="ml-auto text-sm">
                {t("login.forgot")}
              </TextLink>
            )}
          </div>
          <Input
            id="password"
            type="password"
            name="password"
            required
            placeholder={t("login.password_placeholder")}
            value={values.password}
            onChange={(event) => updateValue("password", event.target.value)}
          />
          <InputError message={errors.password} />
        </div>
  
        <div className="flex items-center space-x-3">
          <Checkbox
            id="remember"
            name="remember"
            checked={values.remember}
            onCheckedChange={(checked) => updateValue("remember", Boolean(checked))}
          />
          <Label htmlFor="remember">{t("login.remember")}</Label>
        </div>
  
        <Button type="submit" className="w-full" disabled={isSubmitting}>
          {isSubmitting && <LoaderCircle className="h-4 w-4 animate-spin mr-2" />}
          {t("login.submit")}
        </Button>
      </div>

      {canUseOauth && (
        <div className="space-y-3">
          <div className="flex items-center gap-3 text-xs font-semibold uppercase tracking-[0.3em] text-muted-foreground">
            <span className="h-px flex-1 bg-gray-200 dark:bg-gray-800" aria-hidden />
            {t("login.oauth_divider", "oder")}
            <span className="h-px flex-1 bg-gray-200 dark:bg-gray-800" aria-hidden />
          </div>
          <div className="grid gap-3">
            <Button
              type="button"
              variant="outline"
              onClick={handleGoogleLogin}
              disabled={isSubmitting || isRedirectingToGoogle}
              className="flex w-full items-center justify-center gap-2"
            >
              {isRedirectingToGoogle ? (
                <LoaderCircle className="h-4 w-4 animate-spin" />
              ) : (
                <GoogleIcon className="h-4 w-4" />
              )}
              <span>{t("login.google_cta")}</span>
            </Button>
            <Button
              type="button"
              variant="outline"
              onClick={handleFacebookLogin}
              disabled={isSubmitting || isRedirectingToFacebook}
              className="flex w-full items-center justify-center gap-2"
            >
              {isRedirectingToFacebook ? (
                <LoaderCircle className="h-4 w-4 animate-spin" />
              ) : (
                <FacebookIcon className="h-4 w-4" />
              )}
              <span>{t("login.facebook_cta")}</span>
            </Button>
          </div>
        </div>
      )}

      {Object.values(errors).some(Boolean) && (
        <div className="p-4 bg-red-50 border border-red-200 rounded-md">
          <p className="text-sm text-red-800">{Object.values(errors).filter(Boolean).join(" \u2022 ")}</p>
        </div>
      )}
    </form>
  );
}

function GoogleIcon({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" aria-hidden>
      <path
        fill="#EA4335"
        d="M12 11.999v4.8h6.7c-.3 1.7-2 4.9-6.7 4.9-4 0-7.4-3.3-7.4-7.4S8 6 12 6c2.3 0 3.9 1 4.8 1.9l3.3-3.2C18.1 2.6 15.3 1 12 1 5.9 1 1 5.9 1 12s4.9 11 11 11c6.3 0 10.5-4.4 10.5-10.6 0-.7-.1-1.2-.2-1.8H12z"
      />
    </svg>
  );
}

function FacebookIcon({ className }: { className?: string }) {
  return (
    <svg className={className} viewBox="0 0 24 24" aria-hidden>
      <path
        fill="#1877F2"
        d="M24 12.073C24 5.404 18.627 0 12 0S0 5.404 0 12.073C0 18.1 4.388 23.094 10.125 24v-8.437H7.078v-3.49h3.047V9.43c0-3.014 1.792-4.68 4.533-4.68 1.312 0 2.686.236 2.686.236v2.96h-1.513c-1.49 0-1.954.93-1.954 1.887v2.264h3.328l-.532 3.49h-2.796V24C19.612 23.094 24 18.1 24 12.073Z"
      />
    </svg>
  );
}
