/**
 * Signup Form Component
 * Multi-step signup form using Zod validation
 */

"use client";

import { useState, useCallback, useMemo } from "react";
import Link from "next/link";
import { ErrorMessage } from "@/components/atoms";
import { useSignup } from "../../hooks/use-auth";
import {
  type SignupRequest,
  signupInputSchema,
  buildSignupRequest,
} from "@customer-portal/domain/auth";
import { useZodForm } from "@customer-portal/validation";
import { z } from "zod";

import { MultiStepForm, type FormStep } from "./MultiStepForm";
import { AddressStep } from "./AddressStep";
import { PasswordStep } from "./PasswordStep";
import { PersonalStep } from "./PersonalStep";
import { getCountryCodeByName } from "@/lib/constants/countries";

interface SignupFormProps {
  onSuccess?: () => void;
  onError?: (error: string) => void;
  showLoginLink?: boolean;
  className?: string;
}

/**
 * Frontend form schema - extends domain signupInputSchema with UI-specific fields
 *
 * Single source of truth: Domain layer (signupInputSchema) defines all validation rules
 * Frontend only adds: confirmPassword field and password matching logic
 */
export const signupFormSchema = signupInputSchema
  .extend({
    confirmPassword: z.string().min(1, "Please confirm your password"),
  })
  .refine(data => data.acceptTerms === true, {
    message: "You must accept the terms and conditions",
    path: ["acceptTerms"],
  })
  .superRefine((data, ctx) => {
    if (data.password !== data.confirmPassword) {
      ctx.addIssue({
        code: z.ZodIssueCode.custom,
        path: ["confirmPassword"],
        message: "Passwords do not match",
      });
    }
  });

export type SignupFormValues = z.infer<typeof signupFormSchema>;

export function SignupForm({
  onSuccess,
  onError,
  showLoginLink = true,
  className = "",
}: SignupFormProps) {
  const { signup, loading, error, clearError } = useSignup();
  const [currentStepIndex, setCurrentStepIndex] = useState(0);

  const handleSignup = useCallback(
    async ({ confirmPassword: _confirm, ...formData }: SignupFormValues) => {
      void _confirm;
      clearError();
      try {
        const normalizeCountryCode = (value?: string) => {
          if (!value) return "";
          if (value.length === 2) return value.toUpperCase();
          return getCountryCodeByName(value) ?? value;
        };

        const normalizedAddress = formData.address
          ? (() => {
              const countryValue = formData.address.country || formData.address.countryCode || "";
              const normalizedCountry = normalizeCountryCode(countryValue);
              return {
                ...formData.address,
                country: normalizedCountry,
                countryCode: normalizedCountry,
              };
            })()
          : undefined;

        const request: SignupRequest = buildSignupRequest({
          ...formData,
          ...(normalizedAddress ? { address: normalizedAddress } : {}),
        });
        await signup(request);
        onSuccess?.();
      } catch (err) {
        const message = err instanceof Error ? err.message : "Signup failed";
        onError?.(message);
        throw err; // Re-throw to let useZodForm handle the error state
      }
    },
    [signup, onSuccess, onError, clearError]
  );

  const {
    values,
    errors,
    touched,
    isSubmitting,
    setValue,
    setTouchedField,
    handleSubmit,
    validate,
  } = useZodForm<SignupFormValues>({
    schema: signupFormSchema,
    initialValues: {
      email: "",
      password: "",
      confirmPassword: "",
      firstName: "",
      lastName: "",
      company: "",
      phone: "",
      sfNumber: "",
      address: {
        address1: "",
        address2: "",
        city: "",
        state: "",
        postcode: "",
        country: "",
        countryCode: "",
      },
      nationality: "",
      dateOfBirth: "",
      gender: "male" as const,
      acceptTerms: false,
      marketingConsent: false,
    },
    onSubmit: handleSignup,
  });

  // Handle step change with validation
  const handleStepChange = useCallback((stepIndex: number) => {
    setCurrentStepIndex(stepIndex);
  }, []);

  // Step field definitions (memoized for performance)
  const stepFields = useMemo(
    () => ({
      0: ["firstName", "lastName", "email", "phone"] as const,
      1: ["address"] as const,
      2: ["password", "confirmPassword"] as const,
      3: ["sfNumber", "acceptTerms"] as const,
    }),
    []
  );

  // Validate specific step fields (optimized)
  const validateStep = useCallback(
    (stepIndex: number): boolean => {
      const fields = stepFields[stepIndex as keyof typeof stepFields] || [];

      // Mark fields as touched and check for errors
      fields.forEach(field => setTouchedField(field));

      // Use the validate function to get current validation state
      return validate() || !fields.some(field => Boolean(errors[String(field)]));
    },
    [stepFields, setTouchedField, validate, errors]
  );

  const steps: FormStep[] = [
    {
      key: "personal",
      title: "Personal Information",
      description: "Tell us about yourself",
      content: (
        <PersonalStep
          values={values}
          errors={errors}
          touched={touched}
          setValue={setValue}
          setTouchedField={setTouchedField}
        />
      ),
    },
    {
      key: "address",
      title: "Address",
      description: "Where should we send your SIM?",
      content: (
        <AddressStep
          address={values.address}
          errors={errors}
          touched={touched}
          onAddressChange={address => setValue("address", address)}
          setTouchedField={setTouchedField}
        />
      ),
    },
    {
      key: "security",
      title: "Security",
      description: "Create a secure password",
      content: (
        <PasswordStep
          values={values}
          errors={errors}
          touched={touched}
          setValue={setValue}
          setTouchedField={setTouchedField}
        />
      ),
    },
  ];

  const currentStepFields = stepFields[currentStepIndex as keyof typeof stepFields] ?? [];
  const canProceed =
    currentStepIndex === steps.length - 1
      ? true
      : currentStepFields.every(field => !errors[String(field)]);

  return (
    <div className={`w-full max-w-2xl mx-auto ${className}`}>
      <div className="bg-white shadow-sm rounded-lg border border-gray-200 p-6">
        <div className="mb-8">
          <h1 className="text-2xl font-bold text-gray-900 mb-2">Create Your Account</h1>
          <p className="text-gray-600">
            Join thousands of customers enjoying reliable connectivity
          </p>
        </div>

        <MultiStepForm
          steps={steps}
          currentStep={currentStepIndex}
          onStepChange={handleStepChange}
          onNext={() => {
            if (validateStep(currentStepIndex)) {
              if (currentStepIndex < steps.length - 1) {
                setCurrentStepIndex(currentStepIndex + 1);
              } else {
                void handleSubmit();
              }
            }
          }}
          onPrevious={() => {
            if (currentStepIndex > 0) {
              setCurrentStepIndex(currentStepIndex - 1);
            }
          }}
          isLastStep={currentStepIndex === steps.length - 1}
          isSubmitting={isSubmitting || loading}
          canProceed={canProceed}
        />

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

        {showLoginLink && (
          <div className="mt-6 text-center">
            <p className="text-sm text-gray-600">
              Already have an account?{" "}
              <Link
                href="/auth/login"
                className="font-medium text-blue-600 hover:text-blue-500 transition-colors"
              >
                Sign in
              </Link>
            </p>
          </div>
        )}
      </div>
    </div>
  );
}
