/**
 * Eligibility Check Store
 *
 * Manages state for the public eligibility check flow.
 * Two paths:
 * 1. "Create Account & Submit" (primary) → OTP → Complete Account → Success
 * 2. "Just Submit Request" (secondary) → SF Account + Case → Success
 */

import { create } from "zustand";
import { logger } from "@/core/logger";
import { getErrorMessage } from "@/shared/utils";
import type { JapanAddressFormData } from "@/features/address/components/JapanAddressForm";
import {
  guestEligibilityCheck,
  sendVerificationCode,
  verifyCode,
  signupWithEligibility,
} from "@/features/get-started/api/get-started.api";
import { prepareWhmcsAddressFields } from "@customer-portal/domain/address";

// ============================================================================
// Types
// ============================================================================

export type EligibilityCheckStep = "form" | "otp" | "complete-account" | "success";

export interface EligibilityCheckFormData {
  firstName: string;
  lastName: string;
  email: string;
  address: JapanAddressFormData | null;
}

export interface EligibilityCheckAccountData {
  password: string;
  confirmPassword: string;
  phone: string;
  dateOfBirth: string;
  gender: "male" | "female" | "other" | "";
  acceptTerms: boolean;
  marketingConsent: boolean;
}

export interface EligibilityCheckState {
  // Step management
  step: EligibilityCheckStep;

  // Form data
  formData: EligibilityCheckFormData;
  accountData: EligibilityCheckAccountData;
  isAddressComplete: boolean;

  // Session & success state
  sessionToken: string | null;
  requestId: string | null;
  hasAccount: boolean;

  // OTP state
  attemptsRemaining: number | null;
  resendDisabled: boolean;
  resendCountdown: number;

  // Loading & error
  loading: boolean;
  error: string | null;
  otpError: string | null;

  // Submit type tracking (for loading indicator per button)
  submitType: "create" | "check" | null;

  // Timer reference (internal)
  _resendTimerId: ReturnType<typeof setInterval> | null;

  // Actions
  submitOnly: () => Promise<boolean>;
  submitAndCreate: () => Promise<boolean>;
  verifyOtp: (code: string) => Promise<boolean>;
  resendOtp: () => Promise<boolean>;
  completeAccount: () => Promise<boolean>;

  // Navigation
  goToStep: (step: EligibilityCheckStep) => void;
  goBack: () => void;

  // Form updates
  updateFormData: (data: Partial<EligibilityCheckFormData>) => void;
  updateAccountData: (data: Partial<EligibilityCheckAccountData>) => void;
  setAddressComplete: (isComplete: boolean) => void;

  // Error management
  clearError: () => void;
  clearOtpError: () => void;

  // Timer management
  startResendTimer: () => void;
  stopResendTimer: () => void;

  // Lifecycle
  cleanup: () => void;
  reset: () => void;
}

// ============================================================================
// Initial State
// ============================================================================

const initialFormData: EligibilityCheckFormData = {
  firstName: "",
  lastName: "",
  email: "",
  address: null,
};

const initialAccountData: EligibilityCheckAccountData = {
  password: "",
  confirmPassword: "",
  phone: "",
  dateOfBirth: "",
  gender: "",
  acceptTerms: false,
  marketingConsent: false,
};

const initialState = {
  step: "form" as EligibilityCheckStep,
  formData: initialFormData,
  accountData: initialAccountData,
  isAddressComplete: false,
  sessionToken: null,
  requestId: null,
  hasAccount: false,
  attemptsRemaining: null,
  resendDisabled: false,
  resendCountdown: 0,
  loading: false,
  error: null,
  otpError: null,
  submitType: null as "create" | "check" | null,
  _resendTimerId: null,
};

// ============================================================================
// Store
// ============================================================================

export const useEligibilityCheckStore = create<EligibilityCheckState>()((set, get) => ({
  ...initialState,

  // ---------------------------------------------------------------------------
  // Path 1: "Just Submit Request" (secondary)
  // Creates SF Account + Case without account creation
  // ---------------------------------------------------------------------------
  submitOnly: async () => {
    const { formData, isAddressComplete } = get();

    if (!isAddressComplete || !formData.address) {
      set({ error: "Please complete the address form" });
      return false;
    }

    set({ loading: true, error: null, submitType: "check" });

    try {
      const whmcsAddress = prepareWhmcsAddressFields(formData.address);
      const addr = formData.address;

      // Send both English (WHMCS) and Japanese (Salesforce) address fields
      const result = await guestEligibilityCheck({
        email: formData.email.trim(),
        firstName: formData.firstName.trim(),
        lastName: formData.lastName.trim(),
        address: {
          // English fields (for WHMCS)
          address1: whmcsAddress.address1 || "",
          ...(whmcsAddress.address2 && { address2: whmcsAddress.address2 }),
          city: whmcsAddress.city || "",
          state: whmcsAddress.state || "",
          postcode: whmcsAddress.postcode || "",
          country: "JP",
          // Japanese fields (for Salesforce)
          ...(addr.prefectureJa && { prefectureJa: addr.prefectureJa }),
          ...(addr.cityJa && { cityJa: addr.cityJa }),
          ...(addr.townJa && { townJa: addr.townJa }),
          ...(addr.streetAddress && { streetAddress: addr.streetAddress }),
          ...(addr.buildingName && { buildingName: addr.buildingName }),
          ...(addr.roomNumber && { roomNumber: addr.roomNumber }),
        },
        continueToAccount: false,
      });

      if (result.submitted) {
        set({
          loading: false,
          submitType: null,
          requestId: result.requestId || null,
          hasAccount: false,
          step: "success",
        });
        return true;
      } else {
        set({
          loading: false,
          submitType: null,
          error: result.message || "Failed to submit eligibility check",
        });
        return false;
      }
    } catch (err) {
      const message = getErrorMessage(err);
      logger.error("Failed to submit eligibility check", { error: message, email: formData.email });
      set({ loading: false, submitType: null, error: message });
      return false;
    }
  },

  // ---------------------------------------------------------------------------
  // Path 2: "Create Account & Submit" (primary) - Step 1: Send OTP
  // ---------------------------------------------------------------------------
  submitAndCreate: async () => {
    const { formData, isAddressComplete } = get();

    if (!isAddressComplete || !formData.address) {
      set({ error: "Please complete the address form" });
      return false;
    }

    set({ loading: true, error: null, submitType: "create" });

    try {
      const result = await sendVerificationCode({ email: formData.email.trim() });

      if (result.sent) {
        set({ loading: false, submitType: null, step: "otp" });
        get().startResendTimer();
        return true;
      } else {
        set({
          loading: false,
          submitType: null,
          error: result.message || "Failed to send verification code",
        });
        return false;
      }
    } catch (err) {
      const message = getErrorMessage(err);
      logger.error("Failed to send OTP", { error: message, email: formData.email });
      set({ loading: false, submitType: null, error: message });
      return false;
    }
  },

  // ---------------------------------------------------------------------------
  // Path 2: Step 2 - Verify OTP
  // ---------------------------------------------------------------------------
  verifyOtp: async (code: string) => {
    if (code.length !== 6) return false;

    const { formData } = get();
    set({ loading: true, otpError: null });

    try {
      const result = await verifyCode({
        email: formData.email.trim(),
        code,
      });

      if (result.verified && result.sessionToken) {
        // Clear timer
        get().stopResendTimer();

        // Check account status
        if (result.accountStatus === "portal_exists") {
          set({
            loading: false,
            otpError: "An account already exists with this email. Please log in instead.",
          });
          return false;
        }

        if (result.accountStatus === "whmcs_unmapped") {
          set({
            loading: false,
            otpError:
              "A billing account exists with this email. Please use account linking instead.",
          });
          return false;
        }

        // Proceed to complete account form
        set({
          loading: false,
          sessionToken: result.sessionToken,
          step: "complete-account",
        });
        return true;
      } else {
        set({
          loading: false,
          otpError: result.error || "Verification failed. Please try again.",
          attemptsRemaining: result.attemptsRemaining ?? null,
        });
        return false;
      }
    } catch (err) {
      const message = getErrorMessage(err);
      logger.error("Failed to verify OTP", { error: message, email: formData.email });
      set({ loading: false, otpError: message });
      return false;
    }
  },

  // ---------------------------------------------------------------------------
  // Path 2: Resend OTP
  // ---------------------------------------------------------------------------
  resendOtp: async () => {
    const { formData, resendDisabled, loading } = get();

    // Check both resendDisabled AND loading to prevent race conditions
    // (multiple rapid clicks could pass the check before loading is set)
    if (resendDisabled || loading) return false;

    // Set loading immediately to prevent concurrent calls
    set({ loading: true, otpError: null });

    try {
      const result = await sendVerificationCode({ email: formData.email.trim() });

      if (result.sent) {
        set({ loading: false });
        get().startResendTimer();
        return true;
      } else {
        set({
          loading: false,
          otpError: result.message || "Failed to resend code",
        });
        return false;
      }
    } catch (err) {
      const message = getErrorMessage(err);
      logger.error("Failed to resend OTP", { error: message, email: formData.email });
      set({ loading: false, otpError: message });
      return false;
    }
  },

  // ---------------------------------------------------------------------------
  // Path 2: Step 3 - Complete Account
  // ---------------------------------------------------------------------------
  completeAccount: async () => {
    const { sessionToken, formData, accountData } = get();

    if (!sessionToken) {
      set({ error: "Session expired. Please start over." });
      return false;
    }

    if (!formData.address) {
      set({ error: "Address information is missing." });
      return false;
    }

    set({ loading: true, error: null });

    try {
      const whmcsAddress = prepareWhmcsAddressFields(formData.address);

      const result = await signupWithEligibility({
        sessionToken,
        firstName: formData.firstName.trim(),
        lastName: formData.lastName.trim(),
        address: {
          address1: whmcsAddress.address1 || "",
          ...(whmcsAddress.address2 && { address2: whmcsAddress.address2 }),
          city: whmcsAddress.city || "",
          state: whmcsAddress.state || "",
          postcode: whmcsAddress.postcode || "",
          country: "JP",
        },
        phone: accountData.phone.trim(),
        password: accountData.password,
        dateOfBirth: accountData.dateOfBirth,
        gender: accountData.gender as "male" | "female" | "other",
        acceptTerms: accountData.acceptTerms,
        marketingConsent: accountData.marketingConsent,
      });

      if (result.success) {
        set({
          loading: false,
          requestId: result.eligibilityRequestId || null,
          hasAccount: true,
          step: "success",
        });
        return true;
      } else {
        set({
          loading: false,
          error: result.message || "Failed to create account",
        });
        return false;
      }
    } catch (err) {
      const message = getErrorMessage(err);
      logger.error("Failed to complete account", { error: message, email: formData.email });
      set({ loading: false, error: message });
      return false;
    }
  },

  // ---------------------------------------------------------------------------
  // Navigation
  // ---------------------------------------------------------------------------
  goToStep: (step: EligibilityCheckStep) => {
    const currentStep = get().step;

    // Clear errors when navigating
    set({ step, error: null, otpError: null });

    // Clear session-related data when going backwards
    if (step === "form") {
      // Going back to form - clear everything
      get().stopResendTimer();
      set({ sessionToken: null, attemptsRemaining: null });
    } else if (step === "otp" && currentStep === "complete-account") {
      // Going back from complete-account to OTP - clear session token
      // User will need to re-verify OTP since the previous one was already used
      set({ sessionToken: null, attemptsRemaining: null });
    }
  },

  goBack: () => {
    const { step } = get();
    const stepOrder: EligibilityCheckStep[] = ["form", "otp", "complete-account"];
    const currentIndex = stepOrder.indexOf(step);

    if (currentIndex > 0) {
      const prevStep = stepOrder[currentIndex - 1];
      if (prevStep) {
        get().goToStep(prevStep);
      }
    }
  },

  // ---------------------------------------------------------------------------
  // Form Updates
  // ---------------------------------------------------------------------------
  updateFormData: (data: Partial<EligibilityCheckFormData>) => {
    set({ formData: { ...get().formData, ...data } });
  },

  updateAccountData: (data: Partial<EligibilityCheckAccountData>) => {
    set({ accountData: { ...get().accountData, ...data } });
  },

  setAddressComplete: (isComplete: boolean) => {
    set({ isAddressComplete: isComplete });
  },

  // ---------------------------------------------------------------------------
  // Error Management
  // ---------------------------------------------------------------------------
  clearError: () => {
    set({ error: null });
  },

  clearOtpError: () => {
    set({ otpError: null });
  },

  // ---------------------------------------------------------------------------
  // Timer Management
  // ---------------------------------------------------------------------------
  startResendTimer: () => {
    const { _resendTimerId } = get();

    // Clear existing timer
    if (_resendTimerId) {
      clearInterval(_resendTimerId);
    }

    set({ resendDisabled: true, resendCountdown: 60 });

    const timerId = setInterval(() => {
      const { resendCountdown } = get();

      if (resendCountdown <= 1) {
        clearInterval(timerId);
        set({
          resendDisabled: false,
          resendCountdown: 0,
          _resendTimerId: null,
        });
      } else {
        set({ resendCountdown: resendCountdown - 1 });
      }
    }, 1000);

    set({ _resendTimerId: timerId });
  },

  stopResendTimer: () => {
    const { _resendTimerId } = get();

    if (_resendTimerId) {
      clearInterval(_resendTimerId);
      set({
        _resendTimerId: null,
        resendDisabled: false,
        resendCountdown: 0,
      });
    }
  },

  // ---------------------------------------------------------------------------
  // Lifecycle
  // ---------------------------------------------------------------------------

  /**
   * Cleanup timers without resetting state.
   * Call this on component unmount to prevent memory leaks.
   */
  cleanup: () => {
    const { _resendTimerId } = get();

    if (_resendTimerId) {
      clearInterval(_resendTimerId);
      set({ _resendTimerId: null });
    }
  },

  /**
   * Full reset - clears all state and timers.
   * Call this when starting a new flow.
   */
  reset: () => {
    const { _resendTimerId } = get();

    // Clear timer
    if (_resendTimerId) {
      clearInterval(_resendTimerId);
    }

    set({
      ...initialState,
      _resendTimerId: null,
    });
  },
}));
