/**
 * Password Reset Form Component
 * Form for requesting and resetting passwords - migrated to use Zod validation
 */

"use client";

import { useEffect } from "react";
import Link from "next/link";
import { Button, Input, PasswordInput, ErrorMessage } from "@/components/atoms";
import { FormField } from "@/components/molecules/FormField/FormField";
import { PasswordRequirements, PasswordMatchIndicator } from "..";
import { usePasswordReset } from "../../hooks/use-auth";
import { usePasswordValidation } from "../../hooks/usePasswordValidation";
import { useZodForm } from "@/shared/hooks";
import { parseError } from "@/shared/utils";
import { passwordResetRequestSchema, passwordResetSchema } from "@customer-portal/domain/auth";
import { z } from "zod";

/**
 * Frontend reset form schema - extends domain passwordResetSchema with confirmPassword
 *
 * Single source of truth: Domain layer defines validation rules
 * Frontend only adds: confirmPassword field and password matching logic
 */
const resetFormSchema = passwordResetSchema
  .extend({
    confirmPassword: z.string().min(1, "Please confirm your new password"),
  })
  .superRefine((data, ctx) => {
    if (data.password !== data.confirmPassword) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        path: ["confirmPassword"],
        message: "Passwords do not match",
      });
    }
  });

type ResetFormValues = z.infer<typeof resetFormSchema>;
type PasswordResetRequestData = z.infer<typeof passwordResetRequestSchema>;

const ERROR_BORDER_CLASS = "border-red-300";

interface PasswordResetFormProps {
  mode: "request" | "reset";
  token?: string | undefined;
  onSuccess?: ((email?: string) => void) | undefined;
  onError?: ((error: string) => void) | undefined;
  showLoginLink?: boolean | undefined;
  className?: string | undefined;
}

export function PasswordResetForm({
  mode,
  token,
  onSuccess,
  onError,
  showLoginLink = true,
  className = "",
}: PasswordResetFormProps) {
  const { requestPasswordReset, resetPassword, loading, error, clearError } = usePasswordReset();

  const requestForm = useZodForm<PasswordResetRequestData>({
    schema: passwordResetRequestSchema,
    initialValues: { email: "" },
    onSubmit: async data => {
      try {
        await requestPasswordReset(data.email);
        onSuccess?.(data.email);
      } catch (err) {
        onError?.(parseError(err).message);
        throw err;
      }
    },
  });

  const resetForm = useZodForm<ResetFormValues>({
    schema: resetFormSchema,
    initialValues: { token: token || "", password: "", confirmPassword: "" },
    onSubmit: async ({ confirmPassword: _ignore, ...data }) => {
      void _ignore;
      try {
        await resetPassword(data.token, data.password);
        onSuccess?.();
      } catch (err) {
        onError?.(parseError(err).message);
        throw err;
      }
    },
  });

  const { checks } = usePasswordValidation(resetForm.values.password);
  const showPasswordMatch =
    resetForm.values.confirmPassword.length > 0 && !resetForm.errors["confirmPassword"];
  const passwordsMatch = resetForm.values.password === resetForm.values.confirmPassword;

  // Extract stable reset functions to avoid unnecessary effect runs.
  // The form objects change when internal state changes, but reset is stable.
  const requestFormReset = requestForm.reset;
  const resetFormReset = resetForm.reset;

  // Handle errors from auth hooks
  useEffect(() => {
    if (error) {
      onError?.(error);
    }
  }, [error, onError]);

  // Clear errors when switching modes
  useEffect(() => {
    clearError();
    requestFormReset();
    resetFormReset();
  }, [mode, clearError, requestFormReset, resetFormReset]);

  if (mode === "request") {
    return (
      <RequestModeForm
        requestForm={requestForm}
        loading={loading}
        error={error}
        showLoginLink={showLoginLink}
        className={className}
      />
    );
  }

  return (
    <ResetModeForm
      resetForm={resetForm}
      loading={loading}
      error={error}
      showLoginLink={showLoginLink}
      className={className}
      checks={checks}
      showPasswordMatch={showPasswordMatch}
      passwordsMatch={passwordsMatch}
    />
  );
}

function LoginLink() {
  return (
    <div className="text-center">
      <Link
        href="/auth/login"
        className="text-sm text-primary hover:underline font-medium transition-colors duration-[var(--cp-duration-normal)]"
      >
        Back to login
      </Link>
    </div>
  );
}

function RequestModeForm({
  requestForm,
  loading,
  error,
  showLoginLink,
  className,
}: {
  requestForm: ReturnType<typeof useZodForm<PasswordResetRequestData>>;
  loading: boolean;
  error: string | null;
  showLoginLink: boolean;
  className: string;
}) {
  return (
    <div className={`space-y-6 ${className}`}>
      <form onSubmit={event => void requestForm.handleSubmit(event)} className="space-y-4">
        <FormField
          label="Email address"
          error={requestForm.touched["email"] ? requestForm.errors["email"] : undefined}
          required
        >
          <Input
            type="email"
            placeholder="Enter your email"
            value={requestForm.values.email}
            onChange={e => requestForm.setValue("email", e.target.value)}
            onBlur={() => requestForm.setTouchedField("email")}
            disabled={loading || requestForm.isSubmitting}
            className={requestForm.errors["email"] ? ERROR_BORDER_CLASS : ""}
          />
        </FormField>
        {error && <ErrorMessage>{error}</ErrorMessage>}
        <Button
          type="submit"
          className="w-full"
          disabled={loading || requestForm.isSubmitting}
          loading={loading || requestForm.isSubmitting}
        >
          Send reset link
        </Button>
      </form>
      {showLoginLink && <LoginLink />}
    </div>
  );
}

function ResetModeForm({
  resetForm,
  loading,
  error,
  showLoginLink,
  className,
  checks,
  showPasswordMatch,
  passwordsMatch,
}: {
  resetForm: ReturnType<typeof useZodForm<ResetFormValues>>;
  loading: boolean;
  error: string | null;
  showLoginLink: boolean;
  className: string;
  checks: ReturnType<typeof usePasswordValidation>["checks"];
  showPasswordMatch: boolean;
  passwordsMatch: boolean;
}) {
  return (
    <div className={`space-y-6 ${className}`}>
      <form onSubmit={event => void resetForm.handleSubmit(event)} className="space-y-4">
        <FormField
          label="New password"
          error={resetForm.touched["password"] ? resetForm.errors["password"] : undefined}
          required
        >
          <PasswordInput
            placeholder="Enter new password"
            value={resetForm.values.password}
            onChange={e => resetForm.setValue("password", e.target.value)}
            onBlur={() => resetForm.setTouchedField("password")}
            disabled={loading || resetForm.isSubmitting}
            className={resetForm.errors["password"] ? ERROR_BORDER_CLASS : ""}
          />
          <PasswordRequirements checks={checks} showHint={resetForm.values.password.length === 0} />
        </FormField>
        <FormField
          label="Confirm password"
          error={
            resetForm.touched["confirmPassword"] ? resetForm.errors["confirmPassword"] : undefined
          }
          required
        >
          <PasswordInput
            placeholder="Confirm new password"
            value={resetForm.values.confirmPassword}
            onChange={e => resetForm.setValue("confirmPassword", e.target.value)}
            onBlur={() => resetForm.setTouchedField("confirmPassword")}
            disabled={loading || resetForm.isSubmitting}
            className={resetForm.errors["confirmPassword"] ? ERROR_BORDER_CLASS : ""}
          />
          {showPasswordMatch && <PasswordMatchIndicator passwordsMatch={passwordsMatch} />}
        </FormField>
        {error && <ErrorMessage>{error}</ErrorMessage>}
        <Button
          type="submit"
          className="w-full"
          disabled={loading || resetForm.isSubmitting}
          loading={loading || resetForm.isSubmitting}
        >
          Update password
        </Button>
      </form>
      {showLoginLink && <LoginLink />}
    </div>
  );
}
