<template>
  <form @submit="onSubmit">
    <div class="card-body">
      <div class="row g-3">
        <template v-for="schema in schemas">
          <template v-if="schema.type != 'section'">
            <div :class="`col-md-${schema.cols}`">
              <slot :name="schema.name" v-bind="values">
                <template v-if="schema.type?.includes('-select')">
                  <component
                    :is="schemaTypeToComponent[schema.type ?? 'select']"
                    :name="schema.name"
                    :label="schema.label"
                    :mode="schema.mode"
                    :readonly="schema.readonly"
                    :keyword="
                      formValue[schema.name] ? formValue[schema.name] : null
                    "
                    class="py-0 mb-1"
                  />
                </template>
                <template v-else>
                  <component
                    @change="handleChange"
                    :is="schemaTypeToComponent[schema.type ?? 'text']"
                    :name="schema.name"
                    :label="schema.label"
                    class="py-0 mb-1"
                    :options="schema.options"
                    :option-text="schema.optionText"
                    :option-value="schema.optionValue"
                    :rows="schema.rows"
                    :readonly="schema.readonly"
                    @removePhoto="handleRemoveFile"
                  />
                </template>
              </slot>
            </div>
          </template>
          <template v-if="schema.type == 'section'">
            <h3>{{ schema.title }}</h3>
            <hr />
            <template v-for="childSchema in schema.children">
              <div :class="`col-md-${childSchema.cols}`">
                <slot :name="childSchema.name" v-bind="values">
                  <template v-if="childSchema.type?.includes('-select')">
                    <component
                      :is="schemaTypeToComponent[childSchema.type ?? 'select']"
                      :name="childSchema.name"
                      :label="childSchema.label"
                      :mode="childSchema.mode"
                      :readonly="childSchema.readonly"
                      :keyword="
                        formValue[childSchema.name]
                          ? formValue[childSchema.name]
                          : null
                      "
                      class="py-0 mb-1"
                    />
                  </template>
                  <template v-else>
                    <component
                      :is="schemaTypeToComponent[childSchema.type ?? 'text']"
                      :name="childSchema.name"
                      :label="childSchema.label"
                      class="py-0 mb-1"
                      :options="childSchema.options"
                      :option-text="childSchema.optionText"
                      :option-value="childSchema.optionValue"
                      :rows="childSchema.rows"
                      :readonly="childSchema.readonly"
                      @removePhoto="handleRemoveFile"
                    />
                  </template>
                </slot>
              </div>
            </template>
          </template>
        </template>
      </div>
      <slot name="bottom-action"></slot>
    </div>
    <div v-if="!hideAction" class="card-footer toolbar py-2">
      <div class="d-flex justify-content-end">
        <button class="btn btn-light me-1" @click="$router.go(-1)">
          <i class="pli-back fs-5"></i>
          <span class="d-none d-lg-inline-block ms-lg-2">Back</span>
        </button>
        <button type="submit" class="btn btn-primary">
          <i class="pli-save fs-5"></i>
          <span v-if="saveText" class="d-none d-lg-inline-block ms-lg-2">{{
            saveText
          }}</span>
          <span v-else class="d-none d-lg-inline-block ms-lg-2">{{
            isEdit ? "Update" : "Simpan"
          }}</span>
        </button>
      </div>
    </div>
  </form>
</template>
<script>
import { ref, computed, onMounted, watch } from "vue";
import { useForm } from "vee-validate";
import { object as YupObject } from "yup";
import TextField from "./TextField.vue";
import NumberField from "./NumberField.vue";
import TextArea from "./TextArea.vue";
import DecimalField from "./DecimalField.vue";
import SelectField from "./SelectField.vue";
import Checkbox from "./Checkbox.vue";
import ImageInput from "./ImageInput.vue";
import MultipleImageInput from "./MultipleImageInput.vue";
import DatePicker from "./DatePicker.vue";
import TimePicker from "./TimePicker.vue";
import PasswordField from "./PasswordField.vue";
import FileInput from "./FileInput.vue";

export default {
  props: {
    schemas: {
      default: [],
    },
    formValue: {
      type: Object,
      default: {},
    },
    isEdit: {
      type: Boolean,
      default: false,
    },
    hideAction: {
      type: Boolean,
      default: false,
    },
    saveText: {
      default: null,
    },
  },
  setup(props, ctx) {
    const schemaTypeToComponent = {
      text: TextField,
      password: PasswordField,
      select: SelectField,
      "image-input": ImageInput,
      "multiple-image-input": MultipleImageInput,
      date: DatePicker,
      time: TimePicker,
      textarea: TextArea,
      number: NumberField,
      decimal: DecimalField,
      checkbox: Checkbox,
      "file-input": FileInput,
    };

    const removedFile = ref([]);

    const validation_schema = computed(() => {
      const validations = {};
      props.schemas.forEach((schema) => {
        validations[schema.name] = schema.validation;
      });
      return YupObject(validations);
    });

    const { handleSubmit, resetForm, values, setFieldError } = useForm({
      initialValues: props.formValue,
      validationSchema: validation_schema,
    });

    function onInvalidSubmit({ values, errors, results }) {
      console.log(values); // current form values
      console.log(errors); // a map of field names and their first error message
      console.log(results); // a detailed map of field names and their validation results
    }

    const onSubmit = handleSubmit((values, { resetForm }) => {
      if (values.photo) {
        values.photo = values.photo
          .filter((photo) => photo.id == null || !photo.id)
          .map((photo) => photo.url);
        values.remove_photo = removedFile.value.join(",");
      }
      ctx.emit("formSubmit", values, { resetForm });
    }, onInvalidSubmit);

    const setError = (errors) => {
      Object.keys(errors).forEach((field) => {
        setFieldError(field, errors[field].join(", "));
      });
    };

    const handleRemoveFile = (id) => {
      removedFile.value.push(id);
    };

    onMounted(async () => {
      resetForm({ values: props.formValue });
    });

    const handleChange = (_change) => {
      // console.log(change.target._modelValue);
    };

    watch(
      () => values,
      (newValue, _oldValue) => {
        ctx.emit("data-change", values);
      },
      { deep: true }
    );

    return {
      handleChange,
      values,
      onSubmit,
      schemaTypeToComponent,
      setError,
      handleRemoveFile,
    };
  },
};
</script>
