/**
 * Centralized Services Configuration Store
 *
 * Manages all services configuration state (Internet, SIM) with localStorage persistence.
 * This store serves as the single source of truth for configuration state,
 * eliminating URL param coupling and enabling reliable navigation.
 */

import { create } from "zustand";
import { persist, createJSONStorage } from "zustand/middleware";
import { logger } from "@/core/logger";
import {
  simConfigureFormSchema,
  type SimCardType,
  type ActivationType,
  type MnpData,
} from "@customer-portal/domain/sim";
import {
  buildSimOrderConfigurations,
  type OrderConfigurations,
  type AccessModeValue,
} from "@customer-portal/domain/orders";

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

export interface InternetConfigState {
  planSku: string | null;
  accessMode: AccessModeValue | null;
  installationSku: string | null;
  addonSkus: string[];
  currentStep: number;
}

export interface SimConfigState {
  planSku: string | null;
  simType: SimCardType;
  eid: string;
  selectedAddons: string[];
  activationType: ActivationType;
  scheduledActivationDate: string;
  wantsMnp: boolean;
  mnpData: MnpData;
  currentStep: number;
}

interface CatalogStore {
  // Internet configuration
  internet: InternetConfigState;
  setInternetConfig: (config: Partial<InternetConfigState>) => void;
  resetInternetConfig: () => void;

  // SIM configuration
  sim: SimConfigState;
  setSimConfig: (config: Partial<SimConfigState>) => void;
  resetSimConfig: () => void;

  // Checkout transition helpers
  buildInternetCheckoutParams: () => URLSearchParams | null;
  buildSimCheckoutParams: () => URLSearchParams | null;
  buildServiceOrderConfigurations: () => OrderConfigurations | undefined;
  restoreInternetFromParams: (params: URLSearchParams) => void;
  restoreSimFromParams: (params: URLSearchParams) => void;
}

// ============================================================================
// Initial States
// ============================================================================

const initialInternetState: InternetConfigState = {
  planSku: null,
  accessMode: null,
  installationSku: null,
  addonSkus: [],
  currentStep: 1,
};

const initialSimState: SimConfigState = {
  planSku: null,
  simType: "eSIM",
  eid: "",
  selectedAddons: [],
  activationType: "Immediate",
  scheduledActivationDate: "",
  wantsMnp: false,
  mnpData: {
    reservationNumber: "",
    expiryDate: "",
    phoneNumber: "",
    mvnoAccountNumber: "",
    portingLastName: "",
    portingFirstName: "",
    portingLastNameKatakana: "",
    portingFirstNameKatakana: "",
    portingGender: "",
    portingDateOfBirth: "",
  },
  currentStep: 1,
};

const stringOrUndefined = (value: string | null | undefined): string | undefined => {
  if (typeof value !== "string") return undefined;
  const trimmed = value.trim();
  return trimmed.length > 0 ? trimmed : undefined;
};

const buildSimFormInput = (sim: SimConfigState) => ({
  simType: sim.simType,
  eid: stringOrUndefined(sim.eid),
  selectedAddons: sim.selectedAddons,
  activationType: sim.activationType,
  scheduledActivationDate: stringOrUndefined(sim.scheduledActivationDate),
  wantsMnp: sim.wantsMnp,
  mnpData: sim.wantsMnp
    ? {
        reservationNumber: stringOrUndefined(sim.mnpData.reservationNumber) ?? "",
        expiryDate: stringOrUndefined(sim.mnpData.expiryDate) ?? "",
        phoneNumber: stringOrUndefined(sim.mnpData.phoneNumber) ?? "",
        mvnoAccountNumber: stringOrUndefined(sim.mnpData.mvnoAccountNumber),
        portingLastName: stringOrUndefined(sim.mnpData.portingLastName),
        portingFirstName: stringOrUndefined(sim.mnpData.portingFirstName),
        portingLastNameKatakana: stringOrUndefined(sim.mnpData.portingLastNameKatakana),
        portingFirstNameKatakana: stringOrUndefined(sim.mnpData.portingFirstNameKatakana),
        portingGender: stringOrUndefined(sim.mnpData.portingGender),
        portingDateOfBirth: stringOrUndefined(sim.mnpData.portingDateOfBirth),
      }
    : undefined,
});

/**
 * Set URL param if the value is a non-empty trimmed string.
 * Optionally removes dashes (for date fields).
 */
function setParamIfPresent(
  params: URLSearchParams,
  key: string,
  value: string | undefined,
  removeDashes = false
): void {
  const trimmed = value?.trim();
  if (!trimmed) return;
  params.set(key, removeDashes ? trimmed.replace(/-/g, "") : trimmed);
}

/**
 * Append MNP-related fields to URLSearchParams.
 */
function appendMnpParams(params: URLSearchParams, mnp: MnpData): void {
  setParamIfPresent(params, "mnpNumber", mnp.reservationNumber);
  setParamIfPresent(params, "mnpExpiry", mnp.expiryDate, true);
  setParamIfPresent(params, "mnpPhone", mnp.phoneNumber);
  setParamIfPresent(params, "mvnoAccountNumber", mnp.mvnoAccountNumber);
  setParamIfPresent(params, "portingLastName", mnp.portingLastName);
  setParamIfPresent(params, "portingFirstName", mnp.portingFirstName);
  setParamIfPresent(params, "portingLastNameKatakana", mnp.portingLastNameKatakana);
  setParamIfPresent(params, "portingFirstNameKatakana", mnp.portingFirstNameKatakana);
  setParamIfPresent(params, "portingGender", mnp.portingGender);
  setParamIfPresent(params, "portingDateOfBirth", mnp.portingDateOfBirth, true);
}

/**
 * Parse MNP data from URL params.
 */
function parseMnpDataFromParams(params: URLSearchParams): MnpData {
  return {
    reservationNumber: params.get("mnpNumber") || "",
    expiryDate: params.get("mnpExpiry") || "",
    phoneNumber: params.get("mnpPhone") || "",
    mvnoAccountNumber: params.get("mvnoAccountNumber") || "",
    portingLastName: params.get("portingLastName") || "",
    portingFirstName: params.get("portingFirstName") || "",
    portingLastNameKatakana: params.get("portingLastNameKatakana") || "",
    portingFirstNameKatakana: params.get("portingFirstNameKatakana") || "",
    portingGender: params.get("portingGender") || "",
    portingDateOfBirth: params.get("portingDateOfBirth") || "",
  };
}

/**
 * Parse comma-separated addons string into array.
 */
function parseAddonsFromString(addonsStr: string | null): string[] {
  if (!addonsStr) return [];
  return addonsStr
    .split(",")
    .map(s => s.trim())
    .filter(Boolean);
}

/**
 * Build URLSearchParams for internet checkout from current state.
 */
function buildInternetCheckoutParamsFromState(
  internet: InternetConfigState
): URLSearchParams | null {
  if (!internet.planSku || !internet.accessMode || !internet.installationSku) {
    return null;
  }

  const params = new URLSearchParams({
    type: "internet",
    planSku: internet.planSku,
    accessMode: internet.accessMode,
    installationSku: internet.installationSku,
  });

  if (internet.addonSkus.length > 0) {
    params.set("addons", internet.addonSkus.join(","));
  }

  return params;
}

/**
 * Build URLSearchParams for SIM checkout from current state.
 */
function buildSimCheckoutParamsFromState(sim: SimConfigState): URLSearchParams | null {
  if (!sim.planSku) {
    return null;
  }

  const params = new URLSearchParams({
    type: "sim",
    planSku: sim.planSku,
    simType: sim.simType,
    activationType: sim.activationType,
  });

  setParamIfPresent(params, "eid", sim.simType === "eSIM" ? sim.eid : undefined);
  setParamIfPresent(
    params,
    "scheduledAt",
    sim.activationType === "Scheduled" ? sim.scheduledActivationDate : undefined,
    true
  );

  if (sim.selectedAddons.length > 0) {
    params.set("addons", sim.selectedAddons.join(","));
  }

  if (sim.wantsMnp) {
    params.set("isMnp", "true");
    appendMnpParams(params, sim.mnpData);
  }

  return params;
}

/**
 * Build order configurations from SIM state.
 */
function buildOrderConfigurationsFromSimState(
  sim: SimConfigState
): OrderConfigurations | undefined {
  try {
    const formData = simConfigureFormSchema.parse(buildSimFormInput(sim));
    return buildSimOrderConfigurations(formData);
  } catch (error) {
    logger.warn("Failed to build SIM order configurations from store state", {
      error: error instanceof Error ? error.message : String(error),
    });
    return;
  }
}

/**
 * Parse internet config from URL params.
 */
function parseInternetConfigFromParams(params: URLSearchParams): Partial<InternetConfigState> {
  return {
    planSku: params.get("planSku") || null,
    accessMode: params.get("accessMode") as AccessModeValue | null,
    installationSku: params.get("installationSku") || null,
    addonSkus: parseAddonsFromString(params.get("addons")),
  };
}

/**
 * Parse SIM config from URL params.
 */
function parseSimConfigFromParams(params: URLSearchParams): Partial<SimConfigState> {
  const wantsMnp = params.get("isMnp") === "true";
  return {
    planSku: params.get("planSku") || null,
    simType: (params.get("simType") as SimCardType) || "eSIM",
    activationType: (params.get("activationType") as ActivationType) || "Immediate",
    eid: params.get("eid") || "",
    scheduledActivationDate: params.get("scheduledAt") || "",
    selectedAddons: parseAddonsFromString(params.get("addons")),
    wantsMnp,
    mnpData: wantsMnp ? parseMnpDataFromParams(params) : { ...initialSimState.mnpData },
  };
}

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

export const useCatalogStore = create<CatalogStore>()(
  persist(
    (set, get) => ({
      internet: initialInternetState,
      setInternetConfig: (config: Partial<InternetConfigState>) => {
        set(state => ({ internet: { ...state.internet, ...config } }));
      },
      resetInternetConfig: () => set({ internet: initialInternetState }),

      sim: initialSimState,
      setSimConfig: (config: Partial<SimConfigState>) => {
        set(state => ({ sim: { ...state.sim, ...config } }));
      },
      resetSimConfig: () => set({ sim: initialSimState }),

      buildInternetCheckoutParams: () => buildInternetCheckoutParamsFromState(get().internet),
      buildSimCheckoutParams: () => buildSimCheckoutParamsFromState(get().sim),
      buildServiceOrderConfigurations: () => buildOrderConfigurationsFromSimState(get().sim),

      restoreInternetFromParams: (params: URLSearchParams) => {
        set(state => ({
          internet: { ...state.internet, ...parseInternetConfigFromParams(params) },
        }));
      },
      restoreSimFromParams: (params: URLSearchParams) => {
        set(state => ({ sim: { ...state.sim, ...parseSimConfigFromParams(params) } }));
      },
    }),
    {
      name: "services-config-store",
      storage: createJSONStorage(() => localStorage),
      partialize: state => ({
        internet: {
          ...state.internet,
          currentStep: 1,
        },
        sim: {
          ...state.sim,
          currentStep: 1,
          eid: "",
          wantsMnp: false,
          mnpData: { ...initialSimState.mnpData },
        },
      }),
    }
  )
);

// ============================================================================
// Selectors
// ============================================================================

export const selectInternetConfig = (state: CatalogStore) => state.internet;
export const selectSimConfig = (state: CatalogStore) => state.sim;
export const selectInternetStep = (state: CatalogStore) => state.internet.currentStep;
export const selectSimStep = (state: CatalogStore) => state.sim.currentStep;

// ============================================================================
// Utility Functions
// ============================================================================

/**
 * Clear all services configuration from localStorage
 * Useful for testing or debugging
 */
export const clearCatalogStore = () => {
  if (typeof window !== "undefined") {
    localStorage.removeItem("services-config-store");
  }
};
