<template>
  <w-dialog
    ref="dialogRef"
    :title="$t('re.processor.dialog.httpRequest.title')"
    :can-maximize="false"
    body-padding="0px 0px 0px 0px"
    width="1024px"
    :buttons="[
      {
        icon: 'beenhere',
        label: $t('save'),
        click: save,
      },
    ]"
  >
    <q-splitter :model-value="50" horizontal separator-style="height:3px">
      <template #before>
        <q-tabs v-model="selectedTabRef" no-caps inline-label align="left" class="px-4" @update:model-value="refresh">
          <q-tab name="url" icon="bi-link-45deg" :label="$t('re.processor.httpRequest.tab.url.title')" />
          <q-tab name="authorization" icon="bi-shield-lock" :label="$t('re.processor.httpRequest.tab.authorization.title')" />
          <q-tab name="header" icon="bi-list-task" :label="$t('re.processor.httpRequest.tab.header.title')" />
          <q-tab name="body" icon="bi-receipt" :label="$t('re.processor.httpRequest.tab.body.title')" />
          <q-tab name="advance" icon="bi-gear" :label="$t('re.processor.httpRequest.tab.advance.title')" />
        </q-tabs>
        <q-tab-panels v-model="selectedTabRef" animated class="px-4 pt-2" style="height: 300px">
          <q-tab-panel name="url" style="padding: 0px; height: 100%">
            <w-form
              ref="urlFormRef"
              v-model="modelValue"
              :cols-num="12"
              :fields="[
                {
                  colSpan: 2,
                  name: 'httpMethod',
                  label: $t('re.processor.httpRequest.entity.httpMethod'),
                  type: 'w-select',
                  options: httpMethodTypeOptionsRef,
                  defaultValue: 'GET',
                },
                {
                  firstCol: true,
                  colSpan: 6,
                  name: 'httpUrl',
                  label: $t('re.processor.grid.entity.httpUrl'),
                  type: 'w-code-mirror',
                  height: 224,
                  toolbar: false,
                  lang: 'javascript',
                  placeholder: true,
                  lineWrap: true,
                  lineBreak: false,
                  autoCompletion: autoCompletionManager.autoCompletion(),
                },
                {
                  colSpan: 6,
                  name: 'httpUrlParameterValues',
                  type: 'w-grid',
                  height: 192,
                  title: $t('re.processor.httpRequest.entity.httpUrlParameterValues'),
                  dense: dense,
                  localMode: true,
                  autoFetchData: false,
                  dbClickOperation: 'edit',
                  dndMode: 'local',
                  pageable: false,
                  configButton: false,
                  toolbarConfigure: { noIcon: false },
                  toolbarActions: [
                    {
                      name: 'analyze',
                      label: $t('analyze'),
                      icon: 'bi-tag',
                      click: (args: any) => {
                        args.grid.setLocalData(analyze(urlFormRef.getFieldValue('httpUrl')));
                      },
                    },
                    'separator',
                    'add',
                    'edit',
                    {
                      extend: 'remove',
                      click: (args: any) => {
                        args.grid.removeLocalData(args.selecteds);
                      },
                    },
                  ],
                  columns: parameterValueGridColumns,
                  editor: parameterValueGridEditor,
                  onAfterEditorDataSubmit: (args: any) => {
                    updateGridValues(args.grid, 'httpUrlParameterValues');
                  },
                },
              ]"
            >
            </w-form>
          </q-tab-panel>
          <q-tab-panel name="authorization" style="padding: 0px; height: 100%">
            <w-form
              ref="authorizationFormRef"
              v-model="modelValue"
              :cols-num="12"
              :fields="[
                {
                  colSpan: 6,
                  type: 'w-form-group',
                  layout: 'form',
                  colsNum: 1,
                  fields: [
                    {
                      name: 'httpAuthType',
                      label: $t('re.processor.httpRequest.entity.httpAuthType'),
                      type: 'w-select',
                      options: httpAuthorizationTypeOptionsRef,
                      defaultValue: 'NONE',
                      'onUpdate:modelValue': httpAuthTypeChanged,
                    },
                    {
                      name: 'httpAuthBasicUsername',
                      label: $t('re.processor.httpRequest.entity.httpAuthBasicUsername'),
                      showIf: (args: any) => {
                        return args.form.getFieldValue('httpAuthType') === 'BASIC';
                      },
                      type: 'w-code-mirror',
                      height: 30,
                      toolbar: false,
                      lang: 'javascript',
                      placeholder: true,
                      lineWrap: true,
                      lineBreak: false,
                      autoCompletion: autoCompletionManager.autoCompletion(),
                    },
                    {
                      name: 'httpAuthBasicPassword',
                      label: $t('re.processor.httpRequest.entity.httpAuthBasicPassword'),
                      showIf: (args: any) => {
                        return args.form.getFieldValue('httpAuthType') === 'BASIC';
                      },
                      type: 'w-code-mirror',
                      toolbar: false,
                      lang: 'javascript',
                      height: 30,
                      placeholder: true,
                      lineWrap: true,
                      lineBreak: false,
                      autoCompletion: autoCompletionManager.autoCompletion(),
                    },
                    {
                      name: 'httpAuthBearerToken',
                      label: $t('re.processor.httpRequest.entity.httpAuthBearerToken'),
                      showIf: (args: any) => {
                        return args.form.getFieldValue('httpAuthType') === 'BEARER';
                      },
                      type: 'w-code-mirror',
                      toolbar: false,
                      lang: 'javascript',
                      height: 228,
                      placeholder: true,
                      lineWrap: true,
                      lineBreak: false,
                      autoCompletion: autoCompletionManager.autoCompletion(),
                    },
                  ],
                },
                {
                  colSpan: 6,
                  name: 'httpAuthParameterValues',
                  showIf: (args: any) => {
                    return args.form.getFieldValue('httpAuthType') === 'BEARER' || args.form.getFieldValue('httpAuthType') === 'BASIC';
                  },
                  type: 'w-grid',
                  title: $t('re.processor.httpRequest.entity.httpAuthParameterValues'),
                  height: 236,
                  dense: dense,
                  localMode: true,
                  autoFetchData: false,
                  dbClickOperation: 'edit',
                  dndMode: 'local',
                  pageable: false,
                  configButton: false,
                  toolbarConfigure: { noIcon: false },
                  toolbarActions: [
                    {
                      name: 'analyze',
                      label: $t('analyze'),
                      icon: 'bi-tag',
                      click: (args: any) => {
                        const httpAuthType = authorizationFormRef.getFieldValue('httpAuthType');
                        if (httpAuthType === 'NONE') {
                          args.grid.setLocalData([]);
                        } else if (httpAuthType === 'BASIC') {
                          const httpAuthBasicUsername = authorizationFormRef.getFieldValue('httpAuthBasicUsername');
                          const httpAuthBasicPassword = authorizationFormRef.getFieldValue('httpAuthBasicPassword');
                          args.grid.setLocalData(analyze(httpAuthBasicUsername, httpAuthBasicPassword));
                        } else if (httpAuthType === 'BEARER') {
                          const httpAuthBearerToken = authorizationFormRef.getFieldValue('httpAuthBearerToken');
                          args.grid.setLocalData(analyze(httpAuthBearerToken));
                        }
                      },
                    },
                    'separator',
                    'add',
                    'edit',
                    {
                      extend: 'remove',
                      click: (args: any) => {
                        args.grid.removeLocalData(args.selecteds);
                      },
                    },
                  ],
                  columns: parameterValueGridColumns,
                  editor: parameterValueGridEditor,
                  onAfterEditorDataSubmit: (args: any) => {
                    updateGridValues(args.grid, 'httpAuthParameterValues');
                  },
                },
              ]"
            >
            </w-form>
          </q-tab-panel>
          <q-tab-panel name="header" style="padding: 0px; height: 100%">
            <w-form
              ref="headerFormRef"
              v-model="modelValue"
              :cols-num="12"
              :fields="[
                {
                  colSpan: 6,
                  name: 'httpRequestHeader',
                  label: $t('re.processor.httpRequest.entity.httpRequestHeader'),
                  type: 'w-code-mirror',
                  toolbar: false,
                  lang: 'json',
                  height: 268,
                  placeholder: true,
                  lineWrap: true,
                  lineBreak: true,
                  autoCompletion: autoCompletionManager.autoCompletion(),
                  defaultValue: '{\n\t\n}',
                },
                {
                  colSpan: 6,
                  name: 'httpRequestHeaderParameterValues',
                  type: 'w-grid',
                  title: $t('re.processor.httpRequest.entity.httpRequestHeaderParameterValues'),
                  height: 236,
                  dense: dense,
                  localMode: true,
                  autoFetchData: false,
                  dbClickOperation: 'edit',
                  dndMode: 'local',
                  pageable: false,
                  configButton: false,
                  toolbarConfigure: { noIcon: false },
                  toolbarActions: [
                    {
                      name: 'analyze',
                      label: $t('analyze'),
                      icon: 'bi-tag',
                      click: (args: any) => {
                        args.grid.setLocalData(analyze(headerFormRef.getFieldValue('httpRequestHeader')));
                      },
                    },
                    'separator',
                    'add',
                    'edit',
                    {
                      extend: 'remove',
                      click: (args: any) => {
                        args.grid.removeLocalData(args.selecteds);
                      },
                    },
                  ],
                  columns: parameterValueGridColumns,
                  editor: parameterValueGridEditor,
                  onAfterEditorDataSubmit: (args: any) => {
                    updateGridValues(args.grid, 'httpRequestHeaderParameterValues');
                  },
                },
              ]"
            >
            </w-form>
          </q-tab-panel>
          <q-tab-panel name="body" style="padding: 0px; height: 100%">
            <w-form
              ref="bodyFormRef"
              v-model="modelValue"
              :cols-num="12"
              :fields="[
                {
                  colSpan: 6,
                  name: 'httpRequestBody',
                  label: $t('re.processor.httpRequest.entity.httpRequestBody'),
                  type: 'w-code-mirror',
                  toolbar: false,
                  lang: 'json',
                  height: 268,
                  placeholder: true,
                  lineWrap: true,
                  lineBreak: true,
                  autoCompletion: autoCompletionManager.autoCompletion(),
                  defaultValue: '{\n\t\n}',
                },
                {
                  colSpan: 6,
                  name: 'httpRequestBodyParameterValues',
                  type: 'w-grid',
                  title: $t('re.processor.httpRequest.entity.httpRequestBodyParameterValues'),
                  height: 236,
                  dense: dense,
                  localMode: true,
                  autoFetchData: false,
                  dbClickOperation: 'edit',
                  dndMode: 'local',
                  pageable: false,
                  configButton: false,
                  toolbarConfigure: { noIcon: false },
                  toolbarActions: [
                    {
                      name: 'analyze',
                      label: $t('analyze'),
                      icon: 'bi-tag',
                      click: (args: any) => {
                        args.grid.setLocalData(analyze(bodyFormRef.getFieldValue('httpRequestBody')));
                      },
                    },
                    'separator',
                    'add',
                    'edit',
                    {
                      extend: 'remove',
                      click: (args: any) => {
                        args.grid.removeLocalData(args.selecteds);
                      },
                    },
                  ],
                  columns: parameterValueGridColumns,
                  editor: parameterValueGridEditor,
                  onAfterEditorDataSubmit: (args: any) => {
                    updateGridValues(args.grid, 'httpRequestBodyParameterValues');
                  },
                },
              ]"
            >
            </w-form>
          </q-tab-panel>
          <q-tab-panel name="advance" style="padding: 0px; height: 100%">
            <w-form
              ref="advanceFormRef"
              v-model="modelValue"
              :cols-num="3"
              :fields="[
                {
                  firstCol: true,
                  name: 'httpConnectTimeout',
                  label: $t('re.processor.httpRequest.entity.httpConnectTimeout'),
                  type: 'w-integer',
                  defaultValue: 3000,
                },
                {
                  firstCol: true,
                  name: 'httpRetryCountOnFailure',
                  label: $t('re.processor.httpRequest.entity.httpRetryCountOnFailure'),
                  type: 'w-integer',
                  defaultValue: 0,
                },
                {
                  firstCol: true,
                  name: 'httpAsync',
                  label: $t('re.processor.httpRequest.entity.httpAsync'),
                  type: 'w-checkbox',
                  defaultValue: false,
                },
                {
                  firstCol: true,
                  name: 'httpCache',
                  label: $t('re.processor.httpRequest.entity.httpCache'),
                  type: 'w-checkbox',
                  defaultValue: false,
                },
              ]"
            >
            </w-form>
          </q-tab-panel>
        </q-tab-panels>
      </template>
      <template #after>
        <w-form
          ref="responseFormRef"
          v-model="modelValue"
          class="px-2 pt-1 pb-2"
          :cols-num="1"
          :fields="[
            {
              type: 'w-form-group',
              align: 'right',
              fields: [
                {
                  type: 'q-btn',
                  label: $t('send'),
                  icon: 'bi-send',
                  dense: true,
                  outline: true,
                  onClick: (args: any) => {
                    axios.post(Environment.apiContextPath('/api/re/indicator/processor/sendWebRequest'), modelValue).then((response) => {
                      const result = response.data;
                      if (result.successful) {
                        modelValue.httpResponseBody = result.content;
                      } else {
                        modelValue.httpResponseBody = result.status + ',' + result.error;
                      }
                    });
                    const parameters = Tools.deepClone(autoCompletionManager.getParameters());
                    console.log(parameters);
                    const valueTypes = Tools.deepClone(autoCompletionManager.getValueTypes());
                    responseAutoCompletionManager.setParameters(parameters);
                    responseAutoCompletionManager.setValueTypes(valueTypes);
                  },
                },
              ],
            },
            {
              name: 'httpResponseBody',
              label: $t('re.processor.httpRequest.entity.httpResponseBody'),
              type: 'w-code-mirror',
              toolbar: false,
              lang: 'javascript',
              height: 240,
            },
          ]"
        >
        </w-form>
      </template>
    </q-splitter>
  </w-dialog>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { $t, axios, Environment, EnumTools, Tools, Options } from 'platform-core';
import { reactive } from 'vue';
import { AutoCompletionManager } from '@/views/shared/AutoCompletionManager';
import { PlaceHolder } from '@/utils/PlaceHolder';
import { VariableUtil } from '@/utils/VariableUtil';

import { nextTick } from 'vue';

let context = undefined;
const dense = false;
const dialogRef = ref();
const selectedTabRef = ref('url');
const httpMethodTypeEnumRef = ref();
const httpMethodTypeOptionsRef = ref();
const httpAuthorizationTypeEnumRef = ref();
const httpAuthorizationTypeOptionsRef = ref();

const urlFormRef = ref();
const authorizationFormRef = ref();
const headerFormRef = ref();
const bodyFormRef = ref();
const advanceFormRef = ref();
const responseFormRef = ref();
const httpResponseRef = ref();

const autoCompletionManager = new AutoCompletionManager();
const responseAutoCompletionManager = new AutoCompletionManager();

const modelValue = reactive({
  type: 'HTTP_REQUEST',
  parameter: undefined,
  id: undefined,
  httpMethod: undefined,
  httpUrl: undefined,
  httpUrlParameterValues: undefined,
  httpAuthType: undefined,
  httpAuthBasicUsername: undefined,
  httpAuthBasicPassword: undefined,
  httpAuthBearerToken: undefined,
  httpAuthParameterValues: undefined,
  httpRequestHeader: undefined,
  httpRequestHeaderParameterValues: undefined,
  httpRequestBody: undefined,
  httpRequestBodyParameterValues: undefined,
  httpResponseBody: undefined,
  httpResponseMapping: undefined,
  httpConnectTimeout: 3000,
  httpRetryCountOnFailure: 0,
  httpAsync: false,
  httpCache: false,
});

const parameterValueGridColumns = [
  {
    width: '40%',
    name: 'name',
    label: $t('name'),
    align: 'left',
    sortable: false,
    format: (value: any) => {
      return PlaceHolder.replace(value);
    },
  },
  {
    width: '60%',
    name: 'value',
    label: $t('value'),
    sortable: false,
  },
];
const parameterValueGridEditor = {
  dialog: {
    width: '600px',
  },
  form: {
    colsNum: 1,
    fields: [
      {
        name: 'name',
        label: $t('name'),
        type: 'w-code-mirror',
        toolbar: false,
        lang: 'java',
        height: 30,
        placeholder: true,
        autoCompletion: autoCompletionManager.autoCompletion(),
      },
      {
        name: 'value',
        label: $t('value'),
        type: 'w-text',
      },
    ],
  },
};

const open = async (_context: any) => {
  context = _context;
  if (context.targetType === 'parameter') {
    modelValue.parameter = context.target.id;
  } else if (context.targetType === 'indicator') {
    modelValue.indicator = context.target.id;
  }
  modelValue.id = context.processor.id;
  modelValue.httpMethod = context.processor.httpMethod;
  modelValue.httpUrl = context.processor.httpUrl;
  modelValue.httpUrlParameterValues = context.processor.httpUrlParameterValues;
  modelValue.httpAuthType = context.processor.httpAuthType;
  modelValue.httpAuthBasicUsername = context.processor.httpAuthBasicUsername;
  modelValue.httpAuthBasicPassword = context.processor.httpAuthBasicPassword;
  modelValue.httpAuthBearerToken = context.processor.httpAuthBearerToken;
  modelValue.httpAuthParameterValues = context.processor.httpAuthParameterValues;
  modelValue.httpRequestHeader = context.processor.httpRequestHeader;
  modelValue.httpRequestHeaderParameterValues = context.processor.httpRequestHeaderParameterValues;
  modelValue.httpRequestBody = context.processor.httpRequestBody;
  modelValue.httpRequestBodyParameterValues = context.processor.httpRequestBodyParameterValues;
  modelValue.httpResponseBody = context.processor.httpResponseBody;
  modelValue.httpResponseMapping = context.processor.httpResponseMapping;
  modelValue.httpConnectTimeout = context.processor.httpConnectTimeout;
  modelValue.httpRetryCountOnFailure = context.processor.httpRetryCountOnFailure;
  modelValue.httpAsync = context.processor.httpAsync;
  modelValue.httpCache = context.processor.httpCache;

  init();
  dialogRef.value.show();
  refresh();
};

const close = () => {
  dialogRef.value.hide();
};

const init = () => {
  if (context.targetType === 'parameter') {
    autoCompletionManager.load(Environment.apiContextPath('/api/re/common/parameterAndValueType/findByParameterId/' + context.target.id));
  } else if (context.targetType === 'indicator') {
    autoCompletionManager.load(Environment.apiContextPath('/api/re/common/parameterAndValueType/findByIndicatorId/' + context.target.id));
  }
};

const refresh = () => {
  nextTick(() => {
    let data = Tools.json2Object(modelValue.httpUrlParameterValues) || [];

    let grid = urlFormRef.value?.getFieldComponent('httpUrlParameterValues');
    if (data && data.length > 0) {
      grid?.setLocalData(data);
    }

    data = Tools.json2Object(modelValue.httpAuthParameterValues) || [];
    grid = authorizationFormRef.value?.getFieldComponent('httpAuthParameterValues');
    if (data && data.length > 0) {
      grid?.setLocalData(data);
    }

    data = Tools.json2Object(modelValue.httpRequestHeaderParameterValues) || [];
    grid = headerFormRef.value?.getFieldComponent('httpRequestHeaderParameterValues');
    if (data && data.length > 0) {
      grid?.setLocalData(data);
    }

    data = Tools.json2Object(modelValue.httpRequestBodyParameterValues) || [];
    grid = bodyFormRef.value?.getFieldComponent('httpRequestBodyParameterValues');
    if (data && data.length > 0) {
      grid?.setLocalData(data);
    }
  });
};

const httpAuthTypeChanged = () => {};

const updateGridValues = (grid: any, gridType: string) => {
  const rows = grid.getRows();
  const items: any[] = [];
  if (rows && rows.length > 0) {
    for (const row of rows) {
      items.push({ name: row.name, value: row.value });
    }
  }
  if (gridType === 'httpUrlParameterValues') {
    modelValue.httpUrlParameterValues = Tools.object2Json(items);
  } else if (gridType === 'httpAuthParameterValues') {
    modelValue.httpAuthParameterValues = Tools.object2Json(items);
  } else if (gridType === 'httpRequestHeaderParameterValues') {
    modelValue.httpRequestHeaderParameterValues = Tools.object2Json(items);
  } else if (gridType === 'httpRequestBodyParameterValues') {
    modelValue.httpRequestBodyParameterValues = Tools.object2Json(items);
  }
};

const save = () => {
  axios.put(Environment.apiContextPath('/api/re/model/parameter/processor/' + context.processor.id), modelValue).then((response) => {
    context.processorGrid?.updateLocalData(response.data);
    close();
  });
};

const analyze = (...args: string[]) => {
  if (Tools.isUndefinedOrNull(args) || args.length <= 0) {
    return [];
  }
  let arrays: Array<string> = [];
  for (const arg of args) {
    arrays = arrays.concat(VariableUtil.extract(arg));
  }
  // 排重
  const variables = [...new Set(arrays)];
  const rows: any[] = [];
  for (const item of variables) {
    rows.push({ name: item, value: null });
  }
  return rows;
};

defineExpose({
  open,
  close,
});

EnumTools.fetch(['io.sc.engine.rule.core.enums.HttpMethodType', 'io.sc.engine.rule.core.enums.HttpAuthorizationType']).then((value) => {
  httpMethodTypeEnumRef.value = value.HttpMethodType;
  httpMethodTypeOptionsRef.value = Options.enum(httpMethodTypeEnumRef.value);
  httpAuthorizationTypeEnumRef.value = value.HttpAuthorizationType;
  httpAuthorizationTypeOptionsRef.value = Options.enum(httpAuthorizationTypeEnumRef.value);
});
</script>
