import { components as localComponents } from "./shared/formFields.js";
import { useEditFormStore } from '../store/storeForm.js';
import useScopedStyleMixin from './useScopedStyleMixin.js';
import Label from "./shared/Label/Label.js"
import FormField from "./entities/FormLine/FormField/FormField.js"
import FormLine from "./entities/FormLine/FormLine.js"
import CalcConditions from "./features/Custom/CalcConditions/CalcConditions.js"
import { formBaseElement } from "./formBaseElement.js"

localComponents['edit-form-label'] = Label;
localComponents['edit-form-field'] = FormField;
localComponents['edit-form-line'] = FormLine;

//Поле не найдено - для удобства отладки
const FieldNotFound = {

  name: 'field-not-found',

  props: {
    storeFieldId: String
  },


  template: 'Поле {{storeFieldId}} не найдено'

};
localComponents['field-not-found'] = FieldNotFound;


const FormMessage = { 
  props: { 
    element: Object,
    status: String,
    width: String | Number,
  }, 
  methods: {
    generateHash() {
      return btoa(this.$options.name + Math.random()).slice(0, 8); // Уникальный хэш
    },  
    generateStyles() {
      return `
        .message${this.hash} {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 100%;
        }
        .message__text${this.hash} {
          text-align: start;
        }
        .success${this.hash} {
          color: green;
        }
        .warning${this.hash} {
          color: red;
        }
        .default${this.hash} {
          color: black;
        }
      `
    },
  },
  data() {
    return {
      hash: this.generateHash()
    };
  }, 
  created() {
    const styleId = `style-${this.hash}`;
    if (!document.querySelector(`#${styleId}`)) {
      const style = document.createElement("style");
      style.id = styleId;
      style.textContent = this.generateStyles();
      document.head.appendChild(style);
    }
  },   
  setup(props) {  
    const store = useEditFormStore(); 
    const { data } = Pinia.storeToRefs(store);
    const activeDataSource = props.dataSource || data;
    return { 
      store,
      activeDataSource
    }
  }, 
  name: 'edit-form-message',
  template: /*html*/`
    <article 
      :class="['message' + hash]"
      v-if="isShow"
    >
      <span
        :class="['message__text' + hash, { [status + hash]: status } ]"
        :style="width ? 'width: ' + width + 'px' : ''"
        v-html="message"
      ></span>
    </article>
  `,
  computed:{
    message: function() {
      let message = this.element.template; 
      
      Object.entries(this.store.data).forEach(([key, value]) => {
        message = message.replace("{{" + key + "}}", value); 
      })
      return message; 
    },
    isShow: function() {

      var result = true;
      if (this.element['showOn']) {
          if (typeof this.element['showOnValue'] !== 'undefined') {
              
              if (Array.isArray(this.element['showOnValue'])) {
                  result = false; // По умолчанию false
                  
                  for (let i = 0; i < this.element['showOnValue'].length; i++) {
                      if (this.element['showOnValue'][i] == this.activeDataSource[this.element.showOn]) {
                          result = true; // Если найдено совпадение, устанавливаем true
                          break; // Прерываем цикл
                      }
                  }

              } else {
                  result = (this.activeDataSource[this.element.showOn] == this.element.showOnValue);
              }
          } else {
              result = this.activeDataSource[this.element.showOn];
          }
      }
      return result;

    }
  }
}
localComponents['edit-form-message'] = FormMessage;



/** Сопоставление полей - используется для модулей интеграции */
const IntegrationFieldsMapping = {

  name: 'integration-fields-mapping',

  components: localComponents,

  props: {
    settings: Object,
    dataSource: Object,
    fieldsSource: Object,
    data: Object
  },

  setup(props) {

    var fieldsMap = {};
    var tableFields = {};
    var tableFieldsValues = {};
    //let field = props.fieldsSource[props.storeFieldId];
    const appObject = props.settings.app_object;
    const appAction = props.settings.app_action;
    const actionOptionsDir = props.fieldsSource[appAction]?.optionsFrom?.optionsDir ?? "actions";
    const prefix = props.settings.prefix ?? 'fm_';
    const fieldsList = props.settings.fieldsList ?? "fields";

    return {
      fieldsMap,
      tableFields,
      tableFieldsValues,
      appObject,
      appAction,
      actionOptionsDir,
      prefix,
      fieldsList,
    }
  },

  computed: {
    objectsOptions: function () {
      return this.data.__options[this.appObject] || {};
    },
    isLinkField() {
      return (ident) => {
        const tableId = this.dataSource[this.tableFields[this.prefix + ident].optionsFrom.parent];
        const fieldId = this.dataSource[this.prefix + ident].split(".")[0];
        return window.CB.metadata.isLinkField(tableId, fieldId);
      }
    }    
  },

  methods: {

     hideLabel(ident) {
      const tf = this.tableFields[this.prefix + ident];
      return tf?.showLabel !== false; // true если показывать
    },
    getHelp(ident) {
      if (this.settings.help_unique && this.settings.help_unique === true) {
        const cleanedIdent = ident.replace(/[^a-zA-Z0-9_\-]/g, '');
        return `${this.settings.help}_${cleanedIdent}`;
      }
      return this.settings.help;
    },    
    /**
     * Обновляем список полей для объекта - команды
     */
    updateFieldsMap(valueType, value, value2) {

      this.fieldsMap = {};
      this.tableFields = {}; 

      this.$nextTick(() => {

        let table = "",
            tableId = 0,
            tableMap = {},
            appObjectValue = "",
            appActionValue = "";

        if (valueType == 'full') {

          appObjectValue = value;
          appActionValue = value2;

        } else {

          if (this.settings.app_object_static) {
            appObjectValue = this.settings.app_object_static;
          } else if (this.settings.from_list) {
              //Для Интеграции - берем объект и таблицу из маппинга
              let objectMappingValue = (valueType == 'object') ? value : this.dataSource[this.settings.from_list_value];
              for (tableMap of this.data[this.settings.from_list]) {
                if (tableMap['id'] == objectMappingValue) {
                    appObjectValue = tableMap['external_object_type'];
                    tableId = tableMap['internal_object_id'];
                    break;
                }
              };
          } else {
              table = this.settings.table;
              appObjectValue = (valueType == 'object') ? value : this.dataSource[this.appObject];
          }
          
          appActionValue = (valueType == 'action') ? value : this.dataSource[this.appAction];

        }

        

        if (appObjectValue) {
          //Берем поля из объекта
          this.fieldsMap = this.selectedObjectFieldsMap = this.objectsOptions[appObjectValue]?.[this.fieldsList] ?? {};
        }

        if (appActionValue) {
          //Берем поля из выбранной команды
          appObjectValue = this.objectsOptions[appObjectValue] ? appObjectValue : "__empty";
          let actionFieldsMap = this.objectsOptions[appObjectValue]['__dir'][this.actionOptionsDir][appActionValue]?.[this.fieldsList] ?? {};
          this.fieldsMap = { ...this.fieldsMap, ...actionFieldsMap };
        }

        //Генерируем поля формы для выбора полей КБ
        

        for (let ident in this.fieldsMap) {
          const fm = this.fieldsMap[ident];
          const dataIdent = this.prefix + ident;

          // Значения по умолчанию из маппинга объектов
          if (Object.hasOwn(tableMap, dataIdent) && !Object.hasOwn(this.dataSource, dataIdent)) {
            this.dataSource[dataIdent] = tableMap[dataIdent];
          }

          if (this.settings.fieldsType) {
            // Режим прямой передачи схемы
            this.tableFields[dataIdent] = fm;
          } else {
            let UIFieldType;
            let source;
            switch (this.fieldsMap[ident].type) {
              case 'template':
                UIFieldType = 'template';
                const fsT = this.fieldsMap[ident].field_settings || {};
                if (fsT.options) {
                  this.tableFields[dataIdent] = {
                    type: 'template',
                    options: fsT.options,
                    insertTo: fsT.insertTo,
                    hideTextarea: !!fsT.noTextarea,
                    returnValue: fsT.returnValue || 'value',
                    clearInsertTo: !!fsT.clearInsertTo,
                    escapeBrackets: !!fsT.escapeBrackets,
                    nullLabel: fsT.nullLabel,
                    showLabel: fsT.label !== false
                  };
                  continue;
                }
                source = 'fields';
                break;
              case 'single':
                  const fs = this.fieldsMap[ident].field_settings || {};
                  if (fs.options) {
                    // хотим селект + ОК -> используем наш template-компонент
                    this.tableFields[dataIdent] = {
                      type: 'template',
                      options: fs.options,
                      insertTo: fs.insertTo,
                      hideTextarea: !!fs.noTextarea,
                      nullLabel: fsT.nullLabel,
                      showLabel: fsT.label !== false
                    };
                    continue;
                  }
                  UIFieldType = fs.type || 'dropdown';
                  source = fs.optionsFrom?.source || 'fields';
                break;
              default:
                if (this.fieldsMap[ident].field_settings) {
                  UIFieldType = this.fieldsMap[ident].field_settings.type;
                  source = this.fieldsMap[ident].field_settings.optionsFrom.source;
                } else {
                  UIFieldType = 'dropdown';
                  source = 'fields';
                }
                break;
            }
            this.tableFields[dataIdent] = {
              "type": UIFieldType,
              optionsFrom: {
                "source": source,
                "source": source,
                "parent": this.settings.table,
                "parentId": tableId
                /*"fieldsType": this.fieldsMap[ident].type*/
              }
            };
          }
        }

        this.$forceUpdate();

      });

    },
    generateStyles() {
      return `
        .${this.componentClass}${this.hash} {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 100%;
          gap: 5px;
        }
        .${this.componentClass}__label${this.hash} {
          flex: 1 0 50%;
          display: flex;
          align-items: center;
          justify-content: flex-end;
          gap: 5px;
        }
        .${this.componentClass}__fields${this.hash} {
          flex: 1 0 50%;
          display: flex;
          align-items: center;
          justify-content: flex-start;
          gap: 5px;
        }
      `
    }
  },

  mounted() {
    
    //Если app_object или app_action переданы статично - сразу заполняем fieldsMap
    if ((this.settings.app_object_static && !this.settings.app_action) || this.settings.app_action_static) {
      this.$watch('data.__options', (newValue) => {
        this.updateFieldsMap("full", this.settings.app_object_static, this.settings.app_action_static);
      },
      { immediate: true });
     } else {

      let watchOnObject = 'dataSource.' + this.appObject;
      if (this.settings.from_list) {
        //Для Интеграции - отслеживаем изменение поля с маппингом
        watchOnObject = 'dataSource.' + this.settings.from_list_value;
      }
      //Отслеживаем изменение поля объекта чтобы обновить список полей
      this.$watch(watchOnObject, (appObjectValue, oldVar) => {
        if (appObjectValue !== oldVar) {
          this.updateFieldsMap("object", appObjectValue);
        }
      },
        { immediate: true });

      //Отслеживаем изменение поля команды чтобы обновить список полей
      this.$watch('dataSource.' + this.appAction, (appActionValue, oldVar) => {
        if (appActionValue !== oldVar) {
          this.updateFieldsMap("action", appActionValue);
        }
      },
        { immediate: true });

    }
  },
  mixins: [useScopedStyleMixin],
  data() {
    return {
      componentClass: 'integration-line',
    }
  },
  template: /*html*/`
    <template v-for="(fieldmap, ident) in fieldsMap">
      <div 
        :key="ident"
        :class="componentClass + hash"
        :key="prefix + ident + '_' + Object.keys(fieldsMap).join('_')"
      >
       <div 
          :class="componentClass + '__label' + hash"
        >
          <edit-form-label 
            v-if="hideLabel(ident)"
            :label="fieldmap.name" 
            :help="getHelp(ident)" />
        </div>
        <div
          :class="componentClass + '__fields' + hash"
        >
          <edit-form-field
            :dataSource="dataSource" 
            :fieldsSource="tableFields"  
            :storeFieldId="prefix + ident" 
          />
        </div>
      </div>  
    </template>
  
    `
};

localComponents['integration-fields-mapping'] = IntegrationFieldsMapping;


/** Сопоставление id - используется для модулей интеграции */
const IntegrationIdMapping = {

  name: 'integration-id-mapping',

  components: localComponents,

  props: {
    settings: Object,
    dataSource: Object,
    fieldsSource: Object,
    data: Object
  },

  setup(props) {

    var tableFields = {};

    return {
      tableFields,
    }
  },

  methods: {

    /**
     * Обновляем список полей для объекта - команды
     */
    updateFieldsMap(apps) {

      //Генерируем поля формы для выбора полей КБ
      this.tableFields = {};
      const prefix = this.$t(this.settings.prefix) ?? "ID источника ";
      for (let index in apps) {
        this.tableFields[this.settings.field + "_" + apps[index].id] = {
          "name": prefix + "\"" + apps[index].name + "\"",
          "type": "dropdown",
          "optionsFrom": {
            "source": "fields",
            "parent": this.settings.table,
            "fieldsType": "text",
            "extraOptions": {
              "id": "ID"
            }
          }
        };
      }

      this.$forceUpdate();

    },
    generateStyles() {
      return `
        .${this.componentClass}${this.hash} {
          display: flex;
          align-items: center;
          justify-content: center;
          width: 100%;
          gap: 5px;
        }
        .${this.componentClass}__label${this.hash} {
          flex: 1 0 50%;
          display: flex;
          align-items: center;
          justify-content: flex-end;
          gap: 5px;
        }
        .${this.componentClass}__fields${this.hash} {
          flex: 1 0 50%;
          display: flex;
          align-items: center;
          justify-content: flex-start;
          gap: 5px;
        }
      `
    }
  },

  mounted() {

    //Отслеживаем изменение списка подключений чтобы обновить список полей
    this.$watch('data.' + this.settings.apps, (apps, oldVar) => {
      if (apps !== oldVar) {
        this.updateFieldsMap(apps);
      }
    },
      { immediate: true });

  },
  mixins: [useScopedStyleMixin],
  data() {
    return {
      componentClass: 'integration-line',
    }
  },
  template: /*html*/`
    <template v-for="(fieldmap, ident) in tableFields">
      <div 
        :class="componentClass + hash"
      >
        <div 
          :class="componentClass + '__label' + hash"
        >
          <edit-form-label :label="fieldmap.name" :help="fieldmap.help || settings.help" />
        </div>
        <div
          :class="componentClass + '__fields' + hash"
        >
          <edit-form-field 
            :dataSource="dataSource" 
            :fieldsSource="tableFields"  
            :storeFieldId="ident" 
          />
        </div>
      </div>
    </template>
  
    `
};

localComponents['integration-id-mapping'] = IntegrationIdMapping;

/* Условия запуска вычисления */

localComponents['calc-conditions'] = CalcConditions;

//Кнопка
const FormButton = {

    props: {
        element: Object,
        dataSource: Object,
    },    

    name: 'edit-form-button',
    
    setup(props) {
      const store = useEditFormStore();
      const { data } = Pinia.storeToRefs(store);
      const activeDataSource = props.dataSource || data;

      // Флаг для блокировки кнопки
      const isLoading = Vue.ref(false);

      return { 
          store,
          activeDataSource,
          isLoading
      };
  },

  methods: {
    async buttonAction(e) {
        e.preventDefault();

        if (this.isLoading) return; // Предотвращаем повторное нажатие

        this.isLoading = true; // Блокируем кнопку

        try {
            let response = await fetch("." + this.element.apiAction, {
                method: "GET",
                credentials: "include",
                headers: {
                    'X-Auth-Token': window.x_auth_token || null,
                    'Content-Type': 'application/vnd.api+json'
                }
            });

            response = await response.json();

            if (response['module-settings']) {
                this.store.setData(response['module-settings']);
            }

            let messageIndex = this.element.messageIndex ?? "message";
            jalert(response[messageIndex], '', '', () => {
                window.location.reload(); // Перезагрузка страницы
            });

        } catch (error) {
            console.error("Ошибка при выполнении запроса:", error);
        } finally {
            this.isLoading = false; // Разблокируем кнопку
        }
    }
},    

//    components: localComponents,

   mixins: [formBaseElement],

    template: /*html*/`
        <button 
            type="button" 
            v-if="showOn" 
            v-on:click="buttonAction" 
            class="btn btn-default editform-button"
            :disabled="isLoading"
        >
            <span v-if="isLoading">Загрузка...</span>
            <span v-else>{{$t(element.label)}}</span>
        </button>
    `
};

localComponents['edit-form-button'] = FormButton;
//export default localComponents;
export const components = localComponents;
