import { defineStore } from "pinia"
import { computed, ref } from "vue"
import type { BuilderSchema } from "./formBuilderStore"

/**
 * State for a single PresetBuilder instance. Multiple PresetBuilders
 * can coexist on a page; each is keyed by `builderId`.
 *
 * A preset bundles a name + optional description with an inner
 * FormBuilder-style `BuilderSchema`. The inner schema is owned by
 * `formBuilderStore`; this store only tracks the metadata + a reference
 * to the inner builder id, so the inspector / canvas can read & write
 * the preset name / description without round-tripping through the
 * inner FormBuilder.
 */
export interface PresetBuilderSchema {
  presetName: string
  presetDescription?: string
  schema: BuilderSchema
}

export interface PresetBuilderState {
  presetName: string
  presetDescription: string
  /** Id of the inner FormBuilder schema stored in `formBuilderStore`. */
  innerBuilderId: string
}

let idCounter = 0
function nextId(prefix: string): string {
  idCounter += 1
  return `${prefix}-${Date.now()}-${idCounter}`
}

/** Test helper to make ids deterministic. */
export function __resetPresetBuilderIdCounter(): void {
  idCounter = 0
}

function emptyState(builderId: string): PresetBuilderState {
  return {
    presetName: "",
    presetDescription: "",
    innerBuilderId: `${builderId}::inner`,
  }
}

export const usePresetBuilderStore = defineStore(
  "gx-modui/presetBuilder",
  () => {
    const builders = ref<Record<string, PresetBuilderState>>({})

    function ensureBuilder(builderId: string): PresetBuilderState {
      if (!builders.value[builderId]) {
        builders.value[builderId] = emptyState(builderId)
      }
      return builders.value[builderId]!
    }

    function getState(builderId: string): PresetBuilderState {
      return ensureBuilder(builderId)
    }

    function setName(builderId: string, name: string): void {
      const state = ensureBuilder(builderId)
      state.presetName = name
    }

    function setDescription(builderId: string, description: string): void {
      const state = ensureBuilder(builderId)
      state.presetDescription = description
    }

    function resetBuilder(builderId: string): void {
      delete builders.value[builderId]
    }

    /**
     * Used internally by the composable to seed name + description from
     * a `PresetBuilderSchema`. Inner schema seeding is handled by the
     * composition directly because the inner FormBuilder store has its
     * own `loadSchema` entrypoint.
     */
    function loadMeta(
      builderId: string,
      meta: Pick<PresetBuilderSchema, "presetName" | "presetDescription">,
    ): void {
      const state = ensureBuilder(builderId)
      state.presetName = meta.presetName ?? ""
      state.presetDescription = meta.presetDescription ?? ""
    }

    return {
      builders,
      ensureBuilder,
      getState,
      setName,
      setDescription,
      resetBuilder,
      loadMeta,
    }
  },
)

/** Composable wrapper around `usePresetBuilderStore` for one builder. */
export function usePresetBuilder(builderId: string) {
  const store = usePresetBuilderStore()
  store.ensureBuilder(builderId)
  // Touch the id counter so test helpers can produce deterministic ids
  // when the composable is invoked outside of `ensureBuilder`.
  if (!builderId) {
    nextId("preset")
  }
  return {
    state: computed<PresetBuilderState>(() => store.getState(builderId)),
    setName: (name: string) => store.setName(builderId, name),
    setDescription: (description: string) =>
      store.setDescription(builderId, description),
    loadMeta: (
      meta: Pick<PresetBuilderSchema, "presetName" | "presetDescription">,
    ) => store.loadMeta(builderId, meta),
    reset: () => store.resetBuilder(builderId),
  }
}
