<template>
  <div>
    <template>
      <div class="accordion" id="accordionExample">
        <div
          class="card rounded-0 mb-2"
          v-for="(innerGroupItem, j) in propertyBuilderForm"
          :key="j"
        >
          <!-- v-if="innerGroupItem.key != 'organhMeta'" -->
          <div
            class="card-header p-3"
            :id="'heading' + j"
            type="button"
            data-bs-toggle="collapse"
            :data-bs-target="'#collapse' + j"
            aria-expanded="false"
            :aria-controls="'collapse' + j"
          >
            <div class="d-flex justify-content-between align-items-center">
              <p class="p-0 m-0">
                {{ innerGroupItem.title }}
              </p>

              <!-- <template v-if="selectedCard === j">
                <svg
                  style="transform: rotate(90deg) !important"
                  class="icon icon-Component-359--1"
                >
                  <use xlink:href="#icon-Component-359--1"></use>
                </svg>
              </template> -->
              <template>
                <span class="tavasi tavasi-Component-358--1"></span>
              </template>
            </div>
          </div>

          <div
            :id="'collapse' + j"
            class="collapse"
            :aria-labelledby="'heading' + j"
            data-parent="#accordionExample"
          >
            <div class="card-body">
              <form :key="render">
                <div class="container-fluid">
                  <div class="row">
                    <div
                      v-for="(formElement, index) in refactorItems(
                        innerGroupItem.items
                      )"
                      :class="formElement.colClass ?? 'col-12'"
                    >
                      <component
                        :key="index"
                        :formElement="getValueToFormElement(formElement)"
                        :inputClass="formElement.inputClass"
                        :labelClass="formElement.labelClass"
                        :is="
                          returnComponentName(
                            innerGroupItem,
                            formElement.type,
                            formElement.key
                          )
                        "
                        @take-value="saveComponentValue($event, formElement)"
                        @keydown="saveKeydown($event)"
                        @openModalTags="openModalTags"
                        class="component inside-entity"
                      ></component>
                    </div>
                  </div>
                </div>

                <div
                  v-if="
                    isEditable(innerGroupItem?.key, innerGroupItem.submit_label)
                  "
                  class="d-flex justify-content-end"
                >
                  <button
                    type="submit"
                    class="btn btn-primary mt-3 px-3"
                    @click.prevent="saveProperty(innerGroupItem)"
                  >
                    <span>{{ innerGroupItem.submit_label ?? "ثبت" }}</span>
                  </button>
                </div>
              </form>
            </div>
          </div>
        </div>
      </div>
    </template>
  </div>
</template>

<script>
import repoApi from "@apis/repoApi";
import { mapState } from "pinia";
import HttpService from "@services/httpService";
import { useEntityStore } from "~/systems/search_ui/stores/entityStore";
import { useCommonStore } from "~/systems/search_ui/stores/useCommonStore";
/**
 * @vue-data {Object} [listUpdatedText = {}] - متن‌های به‌روزشده در لیست.
 * @vue-data {undefined} [httpService = undefined] - سرویس HTTP برای درخواست‌ها.
 * @vue-computed {Object} [mapGetters.entity.selectedItemEntityGetter] - مورد انتخاب شده
 * @vue-computed {Object} [mapGetters.userPermisionGetter] - دریافت کننده مجوز کاربر
 * @vue-computed {Object} [mapGetters.currentUser] -  اطلاعات کاربر
 * @vue-event {Function} [mapMutations.SET_ITEM_ENTITY] -  تابع برای قرار دادن موجودیت‌های آیتم
 */
export default {
  // props: ["propertyBuilderForm"],
  props: {
    propertyBuilderForm: {
      default() {
        return [];
      },
      type: Array,
    },
    entityProp: {
      default() {
        return undefined;
      },
    },
    readOnly: {
      default: false,
    },
  },

  beforeMount() {
    this.httpService = new HttpService();
  },
  mounted() {
    // console.log(this.entityProp)
    if (this.entityProp) {
      this.entity_source = this.entityProp;
      this.entity_id = this.entityProp._id ?? undefined;

      this.render++;
    } else this.getEntityBase();
  },
  watch: {
    activeTabGetter(newVal) {
      if (newVal.key == "meta") {
        this.getEntityBase();
      }
    },
  },
  data() {
    return {
      fetchingData: false,
      httpService: undefined,
      entity_source: undefined,
      entity_id : undefined,
      render: 1,
      selectedCard: null,
      listUpdatedText: {},
    };
  },
  computed: {
    ...mapGetters(useEntityStore, [
      // "selectedItemEntityGetter",
      "activeTabGetter",
    ]),
    ...mapGetters(useCommonStore,["userPermisionGetter", "currentUser"]),
  },
  methods: {
    // ...mapMutations("entity", ["SET_ITEM_ENTITY"]),
    openModalTags(item) {
      this.$emit("editPropertyTags", item);
    },
    refactorItems(items) {
      let res = [];
      items.forEach((el) => {
        res.push(el);
      });
      return res;
    },

    toggleCard(j) {
      if (this.selectedCard === j) {
        this.selectedCard = null; // اگر کارت فعال است، غیرفعال شود
      } else {
        this.selectedCard = j; // اگر کارت فعال نیست، فعال شود
      }
    },
    getEntityBase() {
      let self = this;
      this.getEntityInfo().then(() => {
        // if (!self.entity) {
        //   self.entity = self.selectedItemEntityGetter;
        // }
        self.render++;
      });
    },
    /**
     * بررسی امکان ویرایش بر اساس کلید داده شده.
     * @param {String} key - کلیدی که نیاز به بررسی دارد.
     * @returns {Boolean} نتیجه بررسی امکان ویرایش.
     * @description این متد بر اساس کلید داده شده و بررسی سطح دسترسی، امکان ویرایش را تعیین می‌کند.
     * @example
     * const editable = this.isEditable("example_key"); // true or false
     */

    isEditable(key, label = "ثبت") {
      if (this.readOnly) return false;
      if (label == "") return false;
      let res = key ? false : true;
      if (key) {
        let key_root = this.$route.params.key;
        // console.log(key_root)
        res = this.hasPermission(key_root + "_property");

        if (!res) res = this.hasPermission(key + "_edit");
      }

      return res;
    },
    /**
     * بررسی سطح دسترسی کاربر برای یک مجوز خاص.
     * @param {String} permission - مجوزی که نیاز به بررسی دارد.
     * @returns {Boolean} نتیجه بررسی سطح دسترسی.
     * @description این متد سطح دسترسی کاربر فعلی را برای یک مجوز خاص بررسی می‌کند.
     * @example
     * const hasAccess = this.hasPermission("admin_edit"); // true or false
     */
    hasPermission(permission) {
      if (this.currentUser?.user_level > 1) return true;

      if (this.userPermisionGetter && this.userPermisionGetter.length)
        return this.userPermisionGetter.includes(permission);
      return false;
    },
    /**
     * بازگشت نام کامپوننت بر اساس نوع و امکان ویرایش.
     * @param {Object} innerGroupItem - آیتمی که نیاز به بررسی دارد.
     * @param {String} type - نوع ورودی (مثل textarea, select, date).
     * @returns {String} نام کامپوننت مناسب.
     * @description این متد بر اساس نوع ورودی و امکان ویرایش، نام کامپوننت مناسب را برمی‌گرداند.
     * @example
     * const componentName = this.returnComponentName({ key: "description" }, "textarea"); // "TextareaComponent"
     */
    returnComponentName(innerGroupItem, type, key) {
      if (!this.isEditable(innerGroupItem?.key)) return "LabelComponent";

      if (type == "textarea") return "TextareaComponent";
      else if (type == "select") return "SelectComponentDefault";
      else if (type == "date") return "DateComponent";
      else if (type == "tags") return "tagsComponent";
      else return "InputComponent";
    },
    // /**
    //  * تبدیل تاریخ به فرمت فارسی.
    //  * @param {Object} item - آیتمی که شامل تاریخ است.
    //  * @returns {String} تاریخ به فرمت فارسی.
    //  * @description این متد تاریخ موجود در آیتم را به فرمت فارسی تبدیل می‌کند.
    //  * @example
    //  * const persianDate = this.datefa({ begin_date: "2023-05-29T00:00:00Z" }); // "۱۴۰۲/۳/۸"
    //  */
    // // datefa(item) {
    //   var m = this.selectedItemEntityGetter.begin_date;
    //   var d = new Date(m).toLocaleDateString("fa-IR");
    //   return d;
    // },
    /**
     * دریافت مقادیر فرم برای عناصر فرم.
     * @param {Object} elements - عناصر فرم که نیاز به مقداردهی دارند.
     * @returns {Object} عناصر فرم با مقادیر تنظیم شده.
     * @description این متد مقادیر مناسب را به عناصر فرم اختصاص می‌دهد.
     * @example
     * const formElements = this.getValueToFormElement({ key: "name", value: "" });
     * // formElements.value برابر با مقدار موجود در entity است.
     */
    getValueToFormElement(elements) {
      let source = this.entity_source;

      Object.keys(elements).forEach((key, index) => {
        if (source) {
          let key = elements.key.replace("__", ".");
          let value = undefined;
          if (key.includes(".")) {
            let keys = key.split(".");
            let elemntKey = source;
            let kk = "";
            for (var i = 0; i < keys.length - 1; i++) {
              kk = keys[i];
              if (elemntKey[kk]) elemntKey = elemntKey[kk];
            }
            kk = keys[keys.length - 1];
            if (elemntKey[kk]) value = elemntKey[kk];
          } else {
            value = source[key];
          }
          elements["value"] = value;
        }
      });
      return elements;
    },
    /**
     * ذخیره مقدار کامپوننت به صورت موقت.
     * @param {any} value - مقدار جدید کامپوننت.
     * @param {Object} formElement - عنصر فرم که مقدار جدید برای آن تنظیم شده است.
     * @description این متد مقدار جدید کامپوننت را به صورت موقت در لیست به‌روزرسانی‌ها ذخیره می‌کند.
     * @example
     * this.saveComponentValue("new value", { key: "description" });
     */
    saveComponentValue(value, formElement) {
      //در صورت تغییر نگهداری می شود تا وقتی کلید ثبت زد، ذخیره شود
      if (this.entity_source && this.entity_source[formElement.key] != value) {
        this.listUpdatedText[formElement.key] = value;
      }
    },


    async getEntityInfo() {
      if (this.fetchingData) return;

      let key = this.$route.params.key;
      let entityId = this.$route.params.id ?? this.entity_id;
      if(key == "qasection" || key == "rgsection")
        key = "qaqanon"


        // console.log("qaqanon", entityId)
      //if (!(key == "qasection" || key == "rgsection") || !entityId) {
      if (!entityId) {
        return;
      }

      // "public/get/byid/{{index_key}}/{{entity_id}}"
      this.fetchingData = true;
      let url = this.repoMicroServiceName + "/" + repoApi.public.get;

      url = url.replace("{{index_key}}", key);
      url = url.replace("{{entity_id}}", entityId);

      // console.log(url)
      let self = this;
      return await this.httpService
        .getRequest(url)
        .then((res) => {
          // console.log(res);

          self.entity_source = res._source;
          self.entity_id = res._id ?? undefined;
          this.fetchingData = false;
          this.$emit("entityUpdate", this.entity_source);
        })
        .finally(() => {
          this.fetchingData = false;
        });
    },
    /**
     * ذخیره تغییرات در سرور.
     * @description این متد تغییرات موقتی را به سرور ارسال و ذخیره می‌کند.
     * @example
     * this.saveProperty();
     */
    saveProperty(innerGroupItem) {
      // console.log("saveProperty");

      let id = this.$route.params.id ?? this.entity_id;
      let key = this.$route.params.key;

      if (!id) {
        console.log("not id in route params");
        return;
      }

      //  اگر تغییری نداشته باشیم، meta به صورت "{}" خواهد بود.
      if (JSON.stringify(this.listUpdatedText).length > 2) {
        if (this.fetchingData) return;
        this.fetchingData = true;

        let formData = {
          id: id,
          meta: JSON.stringify(this.listUpdatedText),
        };

        let url = "";
        if (key == "qasection" || key == "rgsection") {
          //در این حالت چون مخزن اصل قانون با اجزاء قانون متفاوت هست ، تغییرات در هر دو به نحو خاصی باید إعمال شود.
          url =
            this.repoMicroServiceName + repoApi.public.updateProperty_byRelated;
          url = url.replace("{{appname}}", this.buildName());
          url = url.replace("{{sub_key}}", key);
          key = "qaqanon";
        } else {
          url = this.repoMicroServiceName + repoApi.public.updateEntity;
        }

        url = url.replace("{{index_key}}", key);
        url = url.replace("{{id}}", id);

        this.httpService.postRequest(url, formData).then((res) => {
          this.fetchingData = false;
          this.mySwalToast({
            html: res?.message ?? "با موفقیت ثبت شد.",
          });

          this.getEntityInfo();
        });
      } else {
        this.mySwalToast({
          html: "تغییری جهت ذخیره یافت نشد.",
          icon: "error",
        });
      }
    },


    /**
     * هندلر برای رویداد فشردن کلید.
     * @param {Event} event - رویداد فشردن کلید.
     * @description این متد به عنوان هندلر برای رویداد فشردن کلید استفاده می‌شود.
     * @example
     * // در قالب رویداد keydown در یک المنت
     * <input @keydown="saveKeydown" />
     */
    saveKeydown(event) {
      // console.log(event);
    },
  },
  components: {
    InputComponent: () => import("@components/forms/InputComponent.vue"),
    DateComponent: () => import("@components/forms/DateComponent.vue"),
    TextareaComponent: () => import("@components/forms/TextareaComponent.vue"),
    SelectComponent: () => import("@components/forms/SelectComponent.vue"),
    SelectComponentDefault: () =>
      import("@components/forms/SelectComponentDefault.vue"),
    LabelComponent: () => import("@components/forms/LabelComponent.vue"),
    tagsComponent: () => import("@components/forms/tagsComponent.vue"),
  },
};
</script>

<style lang="scss" scoped>
.card-header {
  div {
    span {
      transform: rotate(90deg);
      transition: transform 0.3s ease;
      color: #000;
    }
  }
}
.card {
  border-radius: 0.6em !important;
  border: none;
}

.card-header {
  border-bottom: none;
  border-radius: 0.6em !important;

  &[aria-expanded="true"] {
    border-bottom-left-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
    background-color: var(--header-color);

    div {
      p {
        color: #fff;
      }
      span {
        transform: rotate(-90deg) !important;
        transition: transform 0.3s ease;
        color: #fff;
      }
    }
  }
}
.btn-primary {
  color: #fff;
}
.show {
  border: 1px solid var(--header-color) !important;
  margin-bottom: 5px;
  border-radius: 0 0 0.6em 0.6em !important;
}
</style>