"use client";

import { Suspense, useEffect, useState, useCallback } from "react";
import type { ReactElement } from "react";
import { useRouter, useSearchParams } from "next/navigation";
import { Loader2 } from "lucide-react";
import type { AuthConfigResponse, AuthProviderConfig } from "@mosaic/shared";
import { API_BASE_URL } from "@/lib/config";
import { signIn } from "@/lib/auth-client";
import { fetchWithRetry } from "@/lib/auth/fetch-with-retry";
import { parseAuthError } from "@/lib/auth/auth-errors";
import { OAuthButton } from "@/components/auth/OAuthButton";
import { LoginForm } from "@/components/auth/LoginForm";
import { AuthDivider } from "@/components/auth/AuthDivider";
import { AuthErrorBanner } from "@/components/auth/AuthErrorBanner";

export default function LoginPage(): ReactElement {
  return (
    <Suspense
      fallback={
        <main className="flex min-h-screen flex-col items-center justify-center p-4 sm:p-8 bg-gray-50">
          <div className="w-full max-w-md space-y-8">
            <div className="text-center">
              <h1 className="text-2xl sm:text-4xl font-bold mb-4">Welcome to Mosaic Stack</h1>
            </div>
            <div className="bg-white p-4 sm:p-8 rounded-lg shadow-md">
              <div
                className="flex items-center justify-center py-8"
                role="status"
                aria-label="Loading authentication options"
              >
                <Loader2 className="h-8 w-8 animate-spin text-blue-500" aria-hidden="true" />
                <span className="sr-only">Loading authentication options</span>
              </div>
            </div>
          </div>
        </main>
      }
    >
      <LoginPageContent />
    </Suspense>
  );
}

function LoginPageContent(): ReactElement {
  const router = useRouter();
  const searchParams = useSearchParams();
  const [config, setConfig] = useState<AuthConfigResponse | null | undefined>(undefined);
  const [loadingConfig, setLoadingConfig] = useState(true);
  const [retryCount, setRetryCount] = useState(0);
  const [oauthLoading, setOauthLoading] = useState<string | null>(null);
  const [credentialsLoading, setCredentialsLoading] = useState(false);
  const [error, setError] = useState<string | null>(null);
  const [urlError, setUrlError] = useState<string | null>(null);

  /* Read ?error= query param on mount and map to PDA-friendly message */
  useEffect(() => {
    const errorCode = searchParams.get("error");
    if (errorCode) {
      const parsed = parseAuthError(errorCode);
      setUrlError(parsed.message);
      // Clean up the URL by removing the error param without triggering navigation
      const nextParams = new URLSearchParams(searchParams.toString());
      nextParams.delete("error");
      const query = nextParams.toString();
      router.replace(query ? `/login?${query}` : "/login");
    }
  }, [searchParams, router]);

  useEffect(() => {
    let cancelled = false;

    async function fetchConfig(): Promise<void> {
      try {
        const response = await fetchWithRetry(`${API_BASE_URL}/auth/config`);
        if (!response.ok) {
          throw new Error("Failed to fetch auth config");
        }
        const data = (await response.json()) as AuthConfigResponse;
        if (!cancelled) {
          setConfig(data);
        }
      } catch (err: unknown) {
        if (!cancelled) {
          console.error("[Auth] Failed to load auth config:", err);
          setConfig(null);
          setUrlError(
            "Unable to load sign-in options. Please refresh the page or try again in a moment."
          );
        }
      } finally {
        if (!cancelled) {
          setLoadingConfig(false);
        }
      }
    }

    void fetchConfig();

    return (): void => {
      cancelled = true;
    };
  }, [retryCount]);

  const oauthProviders: AuthProviderConfig[] =
    config?.providers.filter((p) => p.type === "oauth") ?? [];
  const credentialProviders: AuthProviderConfig[] =
    config?.providers.filter((p) => p.type === "credentials") ?? [];

  const hasOAuth = oauthProviders.length > 0;
  const hasCredentials = credentialProviders.length > 0;

  const handleOAuthLogin = useCallback((providerId: string): void => {
    setOauthLoading(providerId);
    setError(null);
    const callbackURL =
      typeof window !== "undefined" ? new URL("/", window.location.origin).toString() : "/";
    signIn.oauth2({ providerId, callbackURL }).catch((err: unknown) => {
      const message = err instanceof Error ? err.message : String(err);
      console.error(`[Auth] OAuth sign-in initiation failed for ${providerId}:`, message);
      setError("Unable to connect to the sign-in provider. Please try again in a moment.");
      setOauthLoading(null);
    });
  }, []);

  const handleCredentialsLogin = useCallback(
    async (email: string, password: string): Promise<void> => {
      setCredentialsLoading(true);
      setError(null);

      try {
        const result = await signIn.email({ email, password });

        if (result.error) {
          const parsed = parseAuthError(
            result.error.message ? new Error(result.error.message) : result.error
          );
          setError(parsed.message);
        } else {
          router.push("/tasks");
        }
      } catch (err: unknown) {
        const parsed = parseAuthError(err);
        console.error("[Auth] Credentials sign-in failed:", err);
        setError(parsed.message);
      } finally {
        setCredentialsLoading(false);
      }
    },
    [router]
  );

  const handleRetry = useCallback((): void => {
    setConfig(undefined);
    setLoadingConfig(true);
    setUrlError(null);
    setError(null);
    setRetryCount((c) => c + 1);
  }, []);

  return (
    <main className="flex min-h-screen flex-col items-center justify-center p-4 sm:p-8 bg-gray-50">
      <div className="w-full max-w-md space-y-8">
        <div className="text-center">
          <h1 className="text-2xl sm:text-4xl font-bold mb-4">Welcome to Mosaic Stack</h1>
          <p className="text-base sm:text-lg text-gray-600">
            Your personal assistant platform. Organize tasks, events, and projects with a
            PDA-friendly approach.
          </p>
        </div>

        <div className="bg-white p-4 sm:p-8 rounded-lg shadow-md">
          {loadingConfig ? (
            <div
              className="flex items-center justify-center py-8"
              data-testid="loading-spinner"
              role="status"
              aria-label="Loading authentication options"
            >
              <Loader2 className="h-8 w-8 animate-spin text-blue-500" aria-hidden="true" />
              <span className="sr-only">Loading authentication options</span>
            </div>
          ) : config === null ? (
            <div className="space-y-4" data-testid="config-error-state">
              <AuthErrorBanner message={urlError ?? "Unable to load sign-in options."} />
              <div className="flex justify-center">
                <button
                  type="button"
                  onClick={handleRetry}
                  className="px-4 py-2 text-sm font-medium text-white bg-blue-600 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
                >
                  Try again
                </button>
              </div>
            </div>
          ) : (
            <>
              {urlError && (
                <AuthErrorBanner
                  message={urlError}
                  onDismiss={(): void => {
                    setUrlError(null);
                  }}
                />
              )}

              {error && !hasCredentials && (
                <AuthErrorBanner
                  message={error}
                  onDismiss={(): void => {
                    setError(null);
                  }}
                />
              )}

              {hasOAuth &&
                oauthProviders.map((provider) => (
                  <OAuthButton
                    key={provider.id}
                    providerName={provider.name}
                    providerId={provider.id}
                    onClick={(): void => {
                      handleOAuthLogin(provider.id);
                    }}
                    isLoading={oauthLoading === provider.id}
                    disabled={oauthLoading !== null && oauthLoading !== provider.id}
                  />
                ))}

              {hasOAuth && hasCredentials && <AuthDivider />}

              {hasCredentials && (
                <LoginForm
                  onSubmit={handleCredentialsLogin}
                  isLoading={credentialsLoading}
                  error={error}
                />
              )}
            </>
          )}
        </div>
      </div>
    </main>
  );
}
