/**
 * Login Form Component
 * Reusable login form with two-step OTP verification
 *
 * Flow:
 * 1. User enters credentials (email + password)
 * 2. On valid credentials, server returns OTP required response
 * 3. User enters OTP code to complete login
 */

"use client";

import { useState, useCallback } from "react";
import Link from "next/link";
import { useSearchParams } from "next/navigation";
import { Button, Input, ErrorMessage } from "@/components/atoms";
import { FormField } from "@/components/molecules/FormField/FormField";
import { LoginOtpStep } from "../LoginOtpStep";
import { useLoginWithOtp } from "../../hooks/use-auth";
import { loginRequestSchema } from "@customer-portal/domain/auth";
import { useZodForm } from "@/shared/hooks";
import { z } from "zod";
import { getSafeRedirect } from "@/features/auth/utils/route-protection";

interface LoginFormProps {
  onSuccess?: (() => void) | undefined;
  onError?: ((error: string) => void) | undefined;
  showSignupLink?: boolean | undefined;
  showForgotPasswordLink?: boolean | undefined;
  className?: string | undefined;
  redirectTo?: string | undefined;
  initialEmail?: string | undefined;
}

/**
 * Frontend form schema - extends domain loginRequestSchema with UI-specific fields
 */
const loginFormSchema = loginRequestSchema.extend({
  rememberMe: z.boolean().optional(),
});

type LoginFormValues = z.infer<typeof loginFormSchema>;

/** Step in the login flow */
type LoginStep = "credentials" | "otp";

/** OTP state after credentials are validated */
interface OtpState {
  sessionToken: string;
  maskedEmail: string;
  expiresAt: string;
}

export function LoginForm({
  onSuccess,
  onError,
  showSignupLink = true,
  showForgotPasswordLink = true,
  className = "",
  redirectTo,
  initialEmail,
}: LoginFormProps) {
  const searchParams = useSearchParams();
  const { initiateLogin, verifyOtp, loading, error, clearError } = useLoginWithOtp(
    redirectTo ? { redirectTo } : undefined
  );
  const redirectCandidate =
    redirectTo || searchParams?.get("next") || searchParams?.get("redirect");
  const redirect = getSafeRedirect(redirectCandidate, "");
  const redirectQuery = redirect ? `?redirect=${encodeURIComponent(redirect)}` : "";

  // Two-step state management
  const [step, setStep] = useState<LoginStep>("credentials");
  const [otpState, setOtpState] = useState<OtpState | null>(null);

  const handleLogin = useCallback(
    async ({ rememberMe: _rememberMe, ...formData }: LoginFormValues) => {
      void _rememberMe;
      // Note: Don't call clearError() here - the store already sets error: null
      // at the start of initiateLogin, which ensures atomic state updates
      try {
        const result = await initiateLogin(formData);

        // If OTP is required, transition to OTP step
        if (result.requiresOtp) {
          setOtpState({
            sessionToken: result.sessionToken,
            maskedEmail: result.maskedEmail,
            expiresAt: result.expiresAt,
          });
          setStep("otp");
        } else {
          // Direct login (shouldn't happen with current setup, but handle gracefully)
          onSuccess?.();
        }
      } catch (err) {
        const message = err instanceof Error ? err.message : "Login failed";
        onError?.(message);
        throw err;
      }
    },
    [initiateLogin, onSuccess, onError]
  );

  const handleOtpVerify = useCallback(
    async (code: string) => {
      if (!otpState) return;

      // Note: Don't call clearError() here - the store already sets error: null
      // at the start of verifyLoginOtp, which ensures atomic state updates
      try {
        await verifyOtp(otpState.sessionToken, code);
        onSuccess?.();
      } catch (err) {
        const message = err instanceof Error ? err.message : "Verification failed";
        onError?.(message);
        throw err;
      }
    },
    [otpState, verifyOtp, onSuccess, onError]
  );

  const handleBackToCredentials = useCallback(() => {
    setStep("credentials");
    setOtpState(null);
    clearError();
  }, [clearError]);

  const { values, errors, touched, isSubmitting, setValue, setTouchedField, handleSubmit } =
    useZodForm<LoginFormValues>({
      schema: loginFormSchema,
      initialValues: {
        email: initialEmail ?? "",
        password: "",
        rememberMe: false,
      },
      onSubmit: handleLogin,
    });

  // Render OTP step
  if (step === "otp" && otpState) {
    return (
      <div className={`w-full ${className}`}>
        <LoginOtpStep
          sessionToken={otpState.sessionToken}
          maskedEmail={otpState.maskedEmail}
          expiresAt={otpState.expiresAt}
          onVerify={handleOtpVerify}
          onBack={handleBackToCredentials}
          loading={loading}
          error={error}
        />
      </div>
    );
  }

  // Render credentials form
  return (
    <div className={`w-full ${className}`}>
      <form onSubmit={event => void handleSubmit(event)} className="space-y-6">
        <FormField
          label="Email Address"
          error={touched["email"] ? errors["email"] : undefined}
          required
        >
          <Input
            type="email"
            value={values.email}
            onChange={e => setValue("email", e.target.value)}
            onBlur={() => setTouchedField("email")}
            placeholder="Enter your email"
            disabled={isSubmitting || loading}
            className="w-full"
          />
        </FormField>

        <FormField
          label="Password"
          error={touched["password"] ? errors["password"] : undefined}
          required
        >
          <Input
            type="password"
            value={values.password}
            onChange={e => setValue("password", e.target.value)}
            onBlur={() => setTouchedField("password")}
            placeholder="Enter your password"
            disabled={isSubmitting || loading}
            className="w-full"
          />
        </FormField>

        <div className="flex items-center justify-between">
          <div className="flex items-center">
            <input
              id="remember-me"
              name="remember-me"
              type="checkbox"
              checked={values.rememberMe}
              onChange={e => setValue("rememberMe", e.target.checked)}
              disabled={isSubmitting || loading}
              className="h-4 w-4 text-primary focus:ring-primary border-border rounded transition-colors accent-primary"
            />
            <label htmlFor="remember-me" className="ml-2 block text-sm text-muted-foreground">
              Remember me
            </label>
          </div>

          {showForgotPasswordLink && (
            <div className="text-sm">
              <Link
                href="/auth/forgot-password"
                className="font-medium text-primary hover:text-primary-hover transition-colors duration-200"
              >
                Forgot your password?
              </Link>
            </div>
          )}
        </div>

        {error && <ErrorMessage className="text-center">{error}</ErrorMessage>}

        <Button
          type="submit"
          disabled={isSubmitting || loading}
          loading={isSubmitting || loading}
          loadingText="Signing in..."
          className="w-full"
        >
          Sign in
        </Button>

        {showSignupLink && (
          <div className="text-center">
            <p className="text-sm text-muted-foreground">
              Don&apos;t have an account?{" "}
              <Link
                href={`/auth/get-started${redirectQuery}`}
                className="font-medium text-primary hover:text-primary-hover transition-colors duration-200"
              >
                Get started
              </Link>
            </p>
            <p className="text-sm text-muted-foreground mt-1">
              Existing customer?{" "}
              <Link
                href={`/auth/get-started${redirectQuery}`}
                className="font-medium text-primary hover:text-primary-hover transition-colors duration-200"
              >
                Transfer your account
              </Link>
            </p>
          </div>
        )}
      </form>
    </div>
  );
}
