"use client";

import { useAuth } from "@/contexts/auth-context";
import { useTranslations } from "next-intl";
import Image from "next/image";
import { useEffect, useState } from "react";
import { toast } from "sonner";

import {
  AuthCard,
  ForgotPasswordForm,
  LoginCredentialsForm,
  OTPVerificationForm,
  ResetPasswordForm,
} from "@/components/auth";
import apiClient from "@/lib/api/client";
import { AxiosError } from "axios";

export type LoginStep =
  | "credentials"
  | "otp"
  | "forgotPassword"
  | "resetPassword";

interface LoginState {
  step: LoginStep;
  email: string;
  password: string;
  rememberMe: boolean;
}

interface LoginPageProps {
  initialStep?: LoginStep;
  initialEmail?: string;
}

const STEP_QUERY_VALUE: Record<LoginStep, string> = {
  credentials: "credentials",
  otp: "otp",
  forgotPassword: "forgot-password",
  resetPassword: "reset-password",
};

export function LoginPage({
  initialStep = "credentials",
  initialEmail = "",
}: LoginPageProps) {
  const t = useTranslations();
  const { loginWithTokens } = useAuth();

  const [state, setState] = useState<LoginState>({
    step: initialStep,
    email: initialEmail,
    password: "",
    rememberMe: false,
  });
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    if (typeof window === "undefined") {
      return;
    }

    const params = new URLSearchParams(window.location.search);

    if (state.step === "credentials") {
      params.delete("step");
    } else {
      params.set("step", STEP_QUERY_VALUE[state.step]);
    }

    if (
      state.email &&
      (state.step === "otp" || state.step === "resetPassword")
    ) {
      params.set("email", state.email);
    } else {
      params.delete("email");
    }

    const nextSearch = params.toString();
    const nextUrl = `${window.location.pathname}${nextSearch ? `?${nextSearch}` : ""}${window.location.hash}`;
    const currentUrl = `${window.location.pathname}${window.location.search}${window.location.hash}`;

    if (nextUrl !== currentUrl) {
      window.history.replaceState(window.history.state, "", nextUrl);
    }
  }, [state.email, state.step]);

  /**
   * Handle login credentials submission
   * Calls POST /auth/login and transitions to OTP step
   */
  const handleLoginSubmit = async (values: {
    email: string;
    password: string;
    rememberMe: boolean;
  }) => {
    setIsLoading(true);

    try {
      const response = await apiClient.post("/auth/login", {
        email: values.email,
        password: values.password,
        remember: values.rememberMe,
      });

      // Check if OTP is required (nested in data.data)
      if (response.data.data?.requires_otp) {
        // Store credentials and move to OTP step
        setState({
          step: "otp",
          email: values.email,
          password: values.password,
          rememberMe: values.rememberMe,
        });
        toast.success(response.data.message || t("auth.otp.sentMessage", {
            email: response.data.data.email || values.email,
          })
        );
      } else if (response.data.data?.token) {
        // Direct login with tokens (no OTP required)
        const { token, refresh_token, user } = response.data.data;
        loginWithTokens(token, refresh_token, user);
        toast.success(response.data.message || t("auth.loginSuccess"));
      }
    } catch (error: unknown) {
      console.error("Login error:", error);
      const errorMessage =
        error instanceof AxiosError && error.response?.data?.message
          ? error.response.data.message
          : t("auth.errors.invalidCredentials");
      toast.error(errorMessage);
    } finally {
      setIsLoading(false);
    }
  };

  /**
   * Handle OTP verification
   * Calls POST /auth/verify-otp and logs in the user
   */
  const handleOTPSubmit = async (otp: string) => {
    setIsLoading(true);
    try {
      const response = await apiClient.post("/auth/verify-otp", {
        email: state.email,
        otp: otp,
      });

      // Extract tokens and user from response
      const { token, refresh_token, user } = response.data.data;

      // Store tokens and redirect using auth context
      loginWithTokens(token, refresh_token, user);

      toast.success(response.data.message || t("auth.otp.verifySuccess"));
    } catch (error: unknown) {
      console.error("OTP verification error:", error);
      const errorMessage =
        error instanceof AxiosError && error.response?.data?.message
          ? error.response.data.message
          : t("auth.errors.invalidOtp");
      toast.error(errorMessage);
    } finally {
      setIsLoading(false);
    }
  };

  /**
   * Handle OTP resend
   * Calls POST /auth/resend-otp
   */
  const handleOTPResend = async () => {
    try {
      const response = await apiClient.post("/auth/resend-otp", {
        email: state.email,
      });
      toast.success(response.data.message || t("auth.otp.resendSuccess"));
    } catch (error: unknown) {
      console.error("OTP resend error:", error);
      const errorMessage =
        error instanceof AxiosError && error.response?.data?.message
          ? error.response.data.message
          : t("auth.errors.resendFailed");
      toast.error(errorMessage);
    }
  };

  /**
   * Go back to login credentials step
   */
  const handleBackToLogin = () => {
    setState((prev) => ({
      ...prev,
      step: "credentials",
    }));
  };

  /**
   * Handle forgot password - go to forgot password step
   */
  const handleForgotPassword = () => {
    setState((prev) => ({
      ...prev,
      step: "forgotPassword",
    }));
  };

  /**
   * Handle forgot password submission
   * Calls POST /auth/forgot-password
   */
  const handleForgotPasswordSubmit = async (email: string) => {
    setIsLoading(true);
    try {
      const response = await apiClient.post("/auth/forgot-password", {
        email: email,
      });

      // Store email and move to reset password step
      setState((prev) => ({
        ...prev,
        email: email,
        step: "resetPassword",
      }));
      toast.success(response.data.message || t("auth.forgotPassword.codeSent"));
    } catch (error: unknown) {
      console.error("Forgot password error:", error);
      const errorMessage =
        error instanceof AxiosError && error.response?.data?.message
          ? error.response.data.message
          : t("auth.errors.forgotPasswordFailed");
      toast.error(errorMessage);
    } finally {
      setIsLoading(false);
    }
  };

  /**
   * Handle reset password submission
   * Calls POST /auth/reset-password
   */
  const handleResetPasswordSubmit = async (values: {
    otp: string;
    password: string;
    password_confirmation: string;
  }) => {
    setIsLoading(true);
    try {
      const response = await apiClient.post("/auth/reset-password", {
        email: state.email,
        otp: values.otp,
        password: values.password,
        password_confirmation: values.password_confirmation,
      });

      toast.success(response.data.message || t("auth.resetPassword.success"));
      // Go back to login step
      setState({
        step: "credentials",
        email: "",
        password: "",
        rememberMe: false,
      });
    } catch (error: unknown) {
      console.error("Reset password error:", error);
      const errorMessage =
        error instanceof AxiosError && error.response?.data?.message
          ? error.response.data.message
          : t("auth.errors.resetPasswordFailed");
      toast.error(errorMessage);
    } finally {
      setIsLoading(false);
    }
  };

  /**
   * Handle back from reset password to forgot password
   */
  const handleBackToForgotPassword = () => {
    setState((prev) => ({
      ...prev,
      step: "forgotPassword",
    }));
  };

  // Get icon based on current step
  const getIcon = () => {
    switch (state.step) {
      case "credentials":
        return (
          <Image
            src="/icons/waving-hand.svg"
            alt="Welcome"
            width={32}
            height={32}
          />
        );
      case "otp":
        return (
          <Image
            src="/icons/mobile-shield.svg"
            alt="Security"
            width={32}
            height={32}
          />
        );
      case "forgotPassword":
      case "resetPassword":
        return (
          <Image
            src="/icons/lock.svg"
            alt="Lock"
            width={32}
            height={32}
          />
        );
      default:
        return (
          <Image
            src="/icons/waving-hand.svg"
            alt="Welcome"
            width={32}
            height={32}
          />
        );
    }
  };

  // Get title based on current step
  const getTitle = () => {
    switch (state.step) {
      case "credentials":
        return t("auth.login.title");
      case "otp":
        return t("auth.otp.title");
      case "forgotPassword":
        return t("auth.forgotPassword.title");
      case "resetPassword":
        return t("auth.resetPassword.title");
      default:
        return t("auth.login.title");
    }
  };

  // Get subtitle based on current step
  const getSubtitle = () => {
    switch (state.step) {
      case "credentials":
        return t("auth.login.subtitle");
      case "forgotPassword":
        return t("auth.forgotPassword.subtitle");
      case "resetPassword":
        return t("auth.resetPassword.subtitle");
      default:
        return undefined;
    }
  };

  // Render form based on current step
  const renderForm = () => {
    switch (state.step) {
      case "credentials":
        return (
          <LoginCredentialsForm
            onSubmit={handleLoginSubmit}
            onForgotPassword={handleForgotPassword}
            defaultEmail={state.email}
            isLoading={isLoading}
          />
        );
      case "otp":
        return (
          <OTPVerificationForm
            email={state.email}
            onSubmit={handleOTPSubmit}
            onResend={handleOTPResend}
            onBack={handleBackToLogin}
            isLoading={isLoading}
          />
        );
      case "forgotPassword":
        return (
          <ForgotPasswordForm
            onSubmit={handleForgotPasswordSubmit}
            onBackToLogin={handleBackToLogin}
            defaultEmail={state.email}
            isLoading={isLoading}
          />
        );
      case "resetPassword":
        return (
          <ResetPasswordForm
            email={state.email}
            onSubmit={handleResetPasswordSubmit}
            onBack={handleBackToForgotPassword}
            isLoading={isLoading}
          />
        );
      default:
        return null;
    }
  };

  return (
    <AuthCard icon={getIcon()} title={getTitle()} subtitle={getSubtitle()}>
      {renderForm()}
    </AuthCard>
  );
}
