/**
 * Get Started Store
 *
 * Manages state for the unified get-started flow (account creation).
 * For eligibility check without account creation, see the Internet service page.
 */

import { create } from "zustand";
import { logger } from "@/core/logger";
import { getErrorMessage } from "@/shared/utils";
import type { AccountStatus, VerifyCodeResponse } from "@customer-portal/domain/get-started";
import type { AuthResponse } from "@customer-portal/domain/auth";
import * as api from "../api/get-started.api";

export type GetStartedStep =
  | "email"
  | "verification"
  | "account-status"
  | "complete-account"
  | "success";

/**
 * Service context for tracking which service flow the user came from
 * (e.g., SIM plan selection)
 */
export interface ServiceContext {
  type: "sim" | "internet" | "vpn" | null;
  planSku?: string | undefined;
  redirectTo?: string | undefined;
}

/**
 * Address data format used in the get-started form
 */
export interface GetStartedAddress {
  address1?: string | undefined;
  address2?: string | undefined;
  city?: string | undefined;
  state?: string | undefined;
  postcode?: string | undefined;
  country?: string | undefined;
  countryCode?: string | undefined;
}

export interface GetStartedFormData {
  email: string;
  firstName: string;
  lastName: string;
  phone: string;
  address: GetStartedAddress;
  dateOfBirth: string;
  gender: "male" | "female" | "other" | "";
  password: string;
  confirmPassword: string;
  acceptTerms: boolean;
  marketingConsent: boolean;
}

export interface GetStartedState {
  // Current step
  step: GetStartedStep;

  // Session
  sessionToken: string | null;
  emailVerified: boolean;

  // Account status (after verification)
  accountStatus: AccountStatus | null;

  // Form data
  formData: GetStartedFormData;

  // Prefill data from existing account
  prefill: VerifyCodeResponse["prefill"] | null;

  // Handoff token from eligibility check (for pre-filling data after OTP verification)
  handoffToken: string | null;

  // Service context for tracking which service flow the user came from
  serviceContext: ServiceContext | null;

  // Redirect URL (centralized for inline and full-page flows)
  redirectTo: string | null;

  // Whether rendering inline (e.g., on service configure page)
  inline: boolean;

  // Loading and error states
  loading: boolean;
  error: string | null;

  // Verification state
  codeSent: boolean;
  attemptsRemaining: number | null;

  // Actions
  sendVerificationCode: (email: string) => Promise<boolean>;
  verifyCode: (code: string) => Promise<AccountStatus | null>;
  completeAccount: () => Promise<AuthResponse | null>;

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

  // Form updates
  updateFormData: (data: Partial<GetStartedFormData>) => void;

  // Setters for handoff from eligibility check
  setAccountStatus: (status: AccountStatus) => void;
  setPrefill: (prefill: VerifyCodeResponse["prefill"]) => void;
  setSessionToken: (token: string | null) => void;
  setHandoffToken: (token: string | null) => void;
  setServiceContext: (context: ServiceContext | null) => void;
  setRedirectTo: (url: string | null) => void;
  setInline: (inline: boolean) => void;

  // Reset
  reset: () => void;
  clearError: () => void;
}

const initialFormData: GetStartedFormData = {
  email: "",
  firstName: "",
  lastName: "",
  phone: "",
  address: {},
  dateOfBirth: "",
  gender: "",
  password: "",
  confirmPassword: "",
  acceptTerms: false,
  marketingConsent: false,
};

const initialState = {
  step: "email" as GetStartedStep,
  sessionToken: null,
  emailVerified: false,
  accountStatus: null,
  formData: initialFormData,
  prefill: null,
  handoffToken: null,
  serviceContext: null as ServiceContext | null,
  redirectTo: null as string | null,
  inline: false,
  loading: false,
  error: null,
  codeSent: false,
  attemptsRemaining: null,
};

export const useGetStartedStore = create<GetStartedState>()((set, get) => ({
  ...initialState,

  sendVerificationCode: async (email: string) => {
    set({ loading: true, error: null });

    try {
      const result = await api.sendVerificationCode({ email });

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

  verifyCode: async (code: string) => {
    set({ loading: true, error: null });

    try {
      const { handoffToken } = get();
      const result = await api.verifyCode({
        email: get().formData.email,
        code,
        // Pass handoff token if available (from eligibility check flow)
        ...(handoffToken && { handoffToken }),
      });

      if (result.verified && result.sessionToken && result.accountStatus) {
        // Apply prefill data if available
        const prefill = result.prefill;
        const currentFormData = get().formData;

        set({
          loading: false,
          emailVerified: true,
          sessionToken: result.sessionToken,
          accountStatus: result.accountStatus,
          prefill,
          formData: {
            ...currentFormData,
            firstName: prefill?.firstName ?? currentFormData.firstName,
            lastName: prefill?.lastName ?? currentFormData.lastName,
            phone: prefill?.phone ?? currentFormData.phone,
            address: prefill?.address
              ? {
                  address1: prefill.address.address1,
                  address2: prefill.address.address2,
                  city: prefill.address.city,
                  state: prefill.address.state,
                  postcode: prefill.address.postcode,
                  country: prefill.address.country,
                  countryCode: prefill.address.countryCode,
                }
              : currentFormData.address,
          },
          step: "account-status",
        });

        return result.accountStatus;
      } else {
        set({
          loading: false,
          error: result.error ?? "Verification failed",
          attemptsRemaining: result.attemptsRemaining ?? null,
        });
        return null;
      }
    } catch (error) {
      const message = getErrorMessage(error);
      logger.error("Failed to verify code", { error: message });
      set({ loading: false, error: message });
      return null;
    }
  },

  completeAccount: async () => {
    const { sessionToken, formData } = get();

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

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

    try {
      const result = await api.completeAccount({
        sessionToken,
        password: formData.password,
        phone: formData.phone,
        dateOfBirth: formData.dateOfBirth,
        gender: formData.gender as "male" | "female" | "other",
        acceptTerms: formData.acceptTerms,
        marketingConsent: formData.marketingConsent,
      });

      set({ loading: false, step: "success" });

      return result;
    } catch (error) {
      const message = getErrorMessage(error);
      logger.error("Failed to complete account", { error: message });
      set({ loading: false, error: message });
      return null;
    }
  },

  goToStep: (step: GetStartedStep) => {
    set({ step, error: null });
  },

  goBack: () => {
    const { step } = get();
    const stepOrder: GetStartedStep[] = [
      "email",
      "verification",
      "account-status",
      "complete-account",
    ];
    const currentIndex = stepOrder.indexOf(step);
    const prevStep = stepOrder[currentIndex - 1];
    if (currentIndex > 0 && prevStep) {
      set({ step: prevStep, error: null });
    }
  },

  updateFormData: (data: Partial<GetStartedFormData>) => {
    set({ formData: { ...get().formData, ...data } });
  },

  setAccountStatus: (status: AccountStatus) => {
    set({ accountStatus: status });
  },

  setPrefill: (prefill: VerifyCodeResponse["prefill"]) => {
    set({ prefill });
  },

  setSessionToken: (token: string | null) => {
    set({ sessionToken: token, emailVerified: token !== null });
  },

  setHandoffToken: (token: string | null) => {
    set({ handoffToken: token });
  },

  setServiceContext: (context: ServiceContext | null) => {
    set({ serviceContext: context });
  },

  setRedirectTo: (url: string | null) => {
    set({ redirectTo: url });
  },

  setInline: (inline: boolean) => {
    set({ inline });
  },

  reset: () => {
    set(initialState);
  },

  clearError: () => {
    set({ error: null });
  },
}));
