import type { BuilderState } from "@/lib/admin/builder/context";
import type { BuilderScreen, BuilderFunnelState } from "@/lib/admin/builder/types";
import type {
  FunnelDefinition,
  ScreenDefinition,
  ListScreenDefinition,
  ScreenVariantDefinition,
} from "@/lib/funnel/types";

function deepCloneValue<T>(value: T): T {
  if (Array.isArray(value)) {
    return value.map((item) => deepCloneValue(item)) as unknown as T;
  }

  if (value && typeof value === "object") {
    const entries = Object.entries(value as Record<string, unknown>).map(([key, entryValue]) => [
      key,
      deepCloneValue(entryValue),
    ]);
    return Object.fromEntries(entries) as T;
  }

  return value;
}

function withPositions(screens: ScreenDefinition[]): BuilderScreen[] {
  return screens.map((screen, index) => ({
    ...screen,
    position: {
      x: 120 + (index % 4) * 240,
      y: 120 + Math.floor(index / 4) * 200,
    },
  })) as BuilderScreen[];
}

export function deserializeFunnelDefinition(funnel: FunnelDefinition): BuilderState {
  const builderScreens = withPositions(funnel.screens);

  return {
    meta: funnel.meta,
    defaultTexts: funnel.defaultTexts,
    screens: builderScreens,
    selectedScreenId: builderScreens[0]?.id ?? null,
    isDirty: false,
  };
}

export function serializeBuilderState(state: BuilderFunnelState): FunnelDefinition {
  const screens = state.screens;
  const meta: FunnelDefinition["meta"] = {
    ...state.meta,
    firstScreenId: state.meta.firstScreenId ?? state.screens[0]?.id,
  };

  return {
    meta,
    defaultTexts: state.defaultTexts,
    screens,
  };
}

export function cloneScreen(screen: BuilderScreen, overrides?: Partial<BuilderScreen>): BuilderScreen {
  const copy = {
    ...screen,
    ...(screen.template === "list" && 'list' in screen ? {
      list: {
        ...(screen as ListScreenDefinition).list,
        options: (screen as ListScreenDefinition).list.options.map((option) => ({ ...option })),
      }
    } : {}),
    ...(Array.isArray(screen.variants)
      ? {
          variants: screen.variants.map((variant) => ({
            conditions: variant.conditions.map((condition) => ({
              screenId: condition.screenId,
              operator: condition.operator,
              conditionType: condition.conditionType,
              ...(condition.optionIds ? { optionIds: [...condition.optionIds] } : {}),
              ...(condition.values ? { values: [...condition.values] } : {}),
            })),
            ...(variant.overrides
              ? { overrides: deepCloneValue(variant.overrides) as ScreenVariantDefinition<ScreenDefinition>["overrides"] }
              : {}),
          })),
        }
      : {}),
    navigation: screen.navigation
      ? {
          defaultNextScreenId: screen.navigation.defaultNextScreenId,
          ...(screen.navigation.onBackScreenId
            ? { onBackScreenId: screen.navigation.onBackScreenId }
            : {}),
          rules: screen.navigation.rules?.map((rule) => ({
            nextScreenId: rule.nextScreenId,
            conditions: rule.conditions.map((condition) => ({
              screenId: condition.screenId,
              operator: condition.operator,
              conditionType: condition.conditionType,
              ...(condition.optionIds ? { optionIds: [...condition.optionIds] } : {}),
              ...(condition.values ? { values: [...condition.values] } : {}),
            })),
          })),
        }
      : undefined,
  } as BuilderScreen;

  return overrides ? { ...copy, ...overrides } as BuilderScreen : copy;
}

export function toBuilderFunnelState(state: BuilderState): BuilderFunnelState {
  // eslint-disable-next-line @typescript-eslint/no-unused-vars
  const { isDirty: _isDirty, selectedScreenId: _selectedScreenId, ...rest } = state;
  return rest;
}
