import { defineStore } from "pinia"
import { ref } from "vue"

/**
 * Shared form-data state, keyed by `formId` so multiple forms can
 * coexist on a page without colliding. Engine renderers and the
 * FormBuilder all read/write the same shape:
 *
 *   {
 *     values:  { [name]: value },
 *     errors:  { [name]: string[] },
 *     touched: { [name]: boolean },
 *     dirty:   boolean
 *   }
 */
export interface FormState {
  values: Record<string, unknown>
  errors: Record<string, string[]>
  touched: Record<string, boolean>
  dirty: boolean
}

export const useFormDataStore = defineStore("gx-modui/formData", () => {
  const forms = ref<Record<string, FormState>>({})

  function ensureForm(formId: string): FormState {
    if (!forms.value[formId]) {
      forms.value[formId] = {
        values: {},
        errors: {},
        touched: {},
        dirty: false,
      }
    }
    return forms.value[formId]!
  }

  function setInitialValues(
    formId: string,
    values: Record<string, unknown>,
  ): void {
    const form = ensureForm(formId)
    form.values = { ...values }
    form.errors = {}
    form.touched = {}
    form.dirty = false
  }

  function setValue(formId: string, name: string, value: unknown): void {
    const form = ensureForm(formId)
    form.values[name] = value
    form.touched[name] = true
    form.dirty = true
  }

  function setErrors(
    formId: string,
    errors: Record<string, string[] | string>,
  ): void {
    const form = ensureForm(formId)
    const normalised: Record<string, string[]> = {}
    for (const [k, v] of Object.entries(errors)) {
      normalised[k] = Array.isArray(v) ? v : [v]
    }
    form.errors = normalised
  }

  function clearErrors(formId: string, name?: string): void {
    const form = ensureForm(formId)
    if (name === undefined) {
      form.errors = {}
    } else {
      delete form.errors[name]
    }
  }

  function getForm(formId: string): FormState {
    return ensureForm(formId)
  }

  function resetForm(formId: string): void {
    delete forms.value[formId]
  }

  return {
    forms,
    ensureForm,
    setInitialValues,
    setValue,
    setErrors,
    clearErrors,
    getForm,
    resetForm,
  }
})
