<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus';

import { computed, onMounted, ref, watch } from 'vue';

import { EasyFlowFormModal } from '@easyflow/common-ui';

import { Plus, Remove } from '@element-plus/icons-vue';
import {
  ElAlert,
  ElButton,
  ElForm,
  ElFormItem,
  ElIcon,
  ElInput,
  ElMessage,
  ElOption,
  ElRadio,
  ElRadioGroup,
  ElSelect,
} from 'element-plus';

import { api } from '#/api/request';
import UploadAvatar from '#/components/upload/UploadAvatar.vue';
import { $t } from '#/locales';

interface HeaderItem {
  label: string;
  value: string;
}

interface WorkflowCandidate {
  id: string;
  title: string;
}

const emit = defineEmits(['reload']);

const saveForm = ref<FormInstance>();
const dialogVisible = ref(false);
const isAdd = ref(true);
const btnLoading = ref(false);
const categoryList = ref<any[]>([]);
const workflowCandidates = ref<WorkflowCandidate[]>([]);
const tempAddHeaders = ref<HeaderItem[]>([]);
const entity = ref<any>(createDefaultEntity());

const authTypeList = [
  {
    label: 'None',
    value: 'none',
  },
  {
    label: 'Service token / ApiKey',
    value: 'apiKey',
  },
];

const pluginTypeOptions = [
  {
    label: $t('plugin.typeHttp'),
    value: 1,
  },
  {
    label: $t('plugin.typeWorkflow'),
    value: 2,
  },
];

const isWorkflowType = computed(
  () => Number(entity.value.type || 1) === 2,
);

const rules = computed<FormRules>(() => ({
  name: [{ required: true, message: $t('message.required'), trigger: 'blur' }],
  description: [
    { required: true, message: $t('message.required'), trigger: 'blur' },
  ],
  baseUrl: [
    {
      validator: (_rule, value, callback) => {
        if (!isWorkflowType.value && !value) {
          callback(new Error($t('message.required')));
          return;
        }
        callback();
      },
      trigger: 'blur',
    },
  ],
  workflowId: [
    {
      validator: (_rule, value, callback) => {
        if (isWorkflowType.value && !value) {
          callback(new Error($t('message.required')));
          return;
        }
        callback();
      },
      trigger: 'change',
    },
  ],
  authType: [
    {
      validator: (_rule, value, callback) => {
        if (!isWorkflowType.value && !value) {
          callback(new Error($t('message.required')));
          return;
        }
        callback();
      },
      trigger: 'change',
    },
  ],
  position: [
    {
      validator: (_rule, value, callback) => {
        if (
          !isWorkflowType.value &&
          entity.value.authType === 'apiKey' &&
          !value
        ) {
          callback(new Error($t('message.required')));
          return;
        }
        callback();
      },
      trigger: 'change',
    },
  ],
  tokenKey: [
    {
      validator: (_rule, value, callback) => {
        if (
          !isWorkflowType.value &&
          entity.value.authType === 'apiKey' &&
          !value
        ) {
          callback(new Error($t('message.required')));
          return;
        }
        callback();
      },
      trigger: 'blur',
    },
  ],
  tokenValue: [
    {
      validator: (_rule, value, callback) => {
        if (
          !isWorkflowType.value &&
          entity.value.authType === 'apiKey' &&
          !value
        ) {
          callback(new Error($t('message.required')));
          return;
        }
        callback();
      },
      trigger: 'blur',
    },
  ],
}));

watch(
  () => entity.value.type,
  (type) => {
    if (Number(type || 1) === 2) {
      entity.value.baseUrl = '';
      entity.value.authType = 'none';
      entity.value.position = '';
      entity.value.tokenKey = '';
      entity.value.tokenValue = '';
      tempAddHeaders.value = [];
      return;
    }
    entity.value.workflowId = '';
    entity.value.workflowTitle = '';
    entity.value.available = true;
    entity.value.reasonMessage = '';
  },
);

onMounted(async () => {
  await Promise.all([loadCategories(), loadWorkflowCandidates()]);
});

defineExpose({
  openDialog,
});

function createDefaultEntity() {
  return {
    alias: '',
    authType: 'none',
    available: true,
    baseUrl: '',
    categoryIds: [],
    deptId: '',
    description: '',
    englishName: '',
    headers: '',
    icon: '',
    name: '',
    pluginType: 1,
    position: '',
    reasonMessage: '',
    title: '',
    tokenKey: '',
    tokenValue: '',
    type: 1,
    workflowId: '',
    workflowTitle: '',
  };
}

async function loadCategories() {
  const res = await api.get('/api/v1/pluginCategory/list');
  if (res.errorCode === 0) {
    categoryList.value = res.data;
  }
}

async function loadWorkflowCandidates(keyword: string = '') {
  const res = await api.get('/api/v1/plugin/workflowCandidates', {
    params: {
      keyword,
    },
  });
  if (res.errorCode === 0) {
    workflowCandidates.value = Array.isArray(res.data) ? res.data : [];
    ensureCurrentWorkflowOption();
  }
}

function ensureCurrentWorkflowOption() {
  if (!entity.value.workflowId || !entity.value.workflowTitle) {
    return;
  }
  const exists = workflowCandidates.value.some(
    (item) => String(item.id) === String(entity.value.workflowId),
  );
  if (!exists) {
    workflowCandidates.value.unshift({
      id: entity.value.workflowId,
      title: entity.value.workflowTitle,
    });
  }
}

function openDialog(row: any) {
  tempAddHeaders.value = row.headers ? JSON.parse(row.headers) : [];
  isAdd.value = !row.id;
  entity.value = {
    ...createDefaultEntity(),
    ...row,
    authType: row.authType || 'none',
    categoryIds: row.categoryIds?.map((item: any) => item.id) || [],
    type: Number(row.type || row.pluginType || 1),
  };
  ensureCurrentWorkflowOption();
  dialogVisible.value = true;
}

async function syncPluginCategories(pluginId: string, categoryIds: string[]) {
  if (!pluginId) {
    return;
  }
  const relationRes = await api.post(
    '/api/v1/pluginCategoryMapping/updateRelation',
    {
      pluginId,
      categoryIds,
    },
  );
  if (relationRes.errorCode !== 0) {
    throw new Error(relationRes.message || 'sync categories failed');
  }
}

function normalizePayload() {
  const plainEntity = { ...entity.value };
  const categoryIds = [...(plainEntity.categoryIds || [])];
  delete plainEntity.categoryIds;
  if (isWorkflowType.value) {
    plainEntity.baseUrl = '';
    plainEntity.headers = [];
    plainEntity.authType = 'none';
    plainEntity.position = '';
    plainEntity.tokenKey = '';
    plainEntity.tokenValue = '';
  }
  return {
    payload: {
      ...plainEntity,
      headers: isWorkflowType.value ? [] : [...tempAddHeaders.value],
    },
    categoryIds,
  };
}

function save() {
  saveForm.value?.validate(async (valid) => {
    if (!valid) {
      return;
    }
    btnLoading.value = true;
    const { payload, categoryIds } = normalizePayload();
    const requestUrl = isAdd.value
      ? '/api/v1/plugin/plugin/save'
      : '/api/v1/plugin/plugin/update';
    try {
      const res = await api.post(requestUrl, payload);
      if (res.errorCode !== 0) {
        ElMessage.error(res.message);
        return;
      }
      const pluginId = res.data?.id || payload.id || entity.value.id;
      if (!pluginId) {
        throw new Error('插件保存成功，但未返回插件ID');
      }
      await syncPluginCategories(pluginId, categoryIds);
      dialogVisible.value = false;
      ElMessage.success(
        isAdd.value ? $t('message.saveOkMessage') : $t('message.updateOkMessage'),
      );
      emit('reload');
    } catch (error: any) {
      ElMessage.error(error?.message || $t('message.saveFailMessage'));
    } finally {
      btnLoading.value = false;
    }
  });
}

function closeDialog() {
  saveForm.value?.resetFields();
  isAdd.value = true;
  tempAddHeaders.value = [];
  entity.value = createDefaultEntity();
  dialogVisible.value = false;
}

function addHeader() {
  tempAddHeaders.value.push({
    label: '',
    value: '',
  });
}

function removeHeader(index: number) {
  tempAddHeaders.value.splice(index, 1);
}

function handleWorkflowChange(value: string) {
  const target = workflowCandidates.value.find(
    (item) => String(item.id) === String(value),
  );
  entity.value.workflowTitle = target?.title || '';
}
</script>

<template>
  <EasyFlowFormModal
    v-model:open="dialogVisible"
    :title="isAdd ? $t('button.add') : $t('button.edit')"
    :before-close="closeDialog"
    align-center
    :confirm-loading="btnLoading"
    :confirm-text="$t('button.save')"
    :submitting="btnLoading"
    width="lg"
    @confirm="save"
  >
    <ElForm
      ref="saveForm"
      :model="entity"
      status-icon
      :rules="rules"
      label-position="top"
      class="easyflow-modal-form easyflow-modal-form--compact"
    >
      <ElFormItem
        prop="icon"
        :label="$t('plugin.icon')"
        style="display: flex; align-items: center"
      >
        <UploadAvatar v-model="entity.icon" />
      </ElFormItem>
      <ElFormItem prop="type" :label="$t('plugin.type')">
        <ElSelect v-model="entity.type" :disabled="!isAdd">
          <ElOption
            v-for="item in pluginTypeOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </ElSelect>
      </ElFormItem>
      <ElFormItem prop="name" :label="$t('plugin.name')">
        <ElInput
          v-model.trim="entity.name"
          :placeholder="$t('plugin.placeholder.name')"
        />
      </ElFormItem>
      <ElFormItem prop="description" :label="$t('plugin.description')">
        <ElInput
          v-model.trim="entity.description"
          :rows="4"
          type="textarea"
          :placeholder="$t('plugin.placeholder.description')"
        />
      </ElFormItem>
      <ElFormItem prop="categoryIds" :label="$t('plugin.category')">
        <ElSelect
          v-model="entity.categoryIds"
          multiple
          collapse-tags
          collapse-tags-tooltip
          :max-collapse-tags="3"
        >
          <ElOption
            v-for="item in categoryList"
            :key="item.id"
            :label="item.name"
            :value="item.id"
          />
        </ElSelect>
      </ElFormItem>
      <template v-if="isWorkflowType">
        <ElAlert
          type="info"
          :closable="false"
          show-icon
          class="mb-4"
          :title="$t('plugin.workflowPluginHint')"
        />
        <ElFormItem prop="workflowId" :label="$t('plugin.workflowId')">
          <ElSelect
            v-model="entity.workflowId"
            filterable
            remote
            reserve-keyword
            :remote-method="loadWorkflowCandidates"
            :placeholder="$t('plugin.placeholder.workflow')"
            @change="handleWorkflowChange"
          >
            <ElOption
              v-for="item in workflowCandidates"
              :key="item.id"
              :label="item.title"
              :value="item.id"
            />
          </ElSelect>
          <div class="form-helper-text">
            {{ $t('plugin.onlyPublishedWorkflow') }}
          </div>
        </ElFormItem>
        <ElAlert
          v-if="!entity.available && entity.reasonMessage"
          type="warning"
          :closable="false"
          show-icon
          :title="$t('plugin.workflowPluginUnavailable')"
          :description="entity.reasonMessage"
        />
      </template>
      <template v-else>
        <ElFormItem prop="baseUrl" :label="$t('plugin.baseUrl')">
          <ElInput v-model.trim="entity.baseUrl" />
        </ElFormItem>
        <ElFormItem prop="Headers" label="Headers">
          <div
            v-for="(item, index) in tempAddHeaders"
            :key="index"
            class="headers-container-reduce flex flex-row gap-4"
          >
            <div class="head-con-content flex flex-row gap-4">
              <ElInput v-model.trim="item.label" placeholder="header name" />
              <ElInput v-model.trim="item.value" placeholder="header value" />
              <ElIcon
                size="20"
                style="cursor: pointer"
                @click="removeHeader(index)"
              >
                <Remove />
              </ElIcon>
            </div>
          </div>
          <ElButton class="addHeadersBtn" @click="addHeader">
            <ElIcon size="18" style="margin-right: 4px">
              <Plus />
            </ElIcon>
            {{ $t('button.add') }}headers
          </ElButton>
        </ElFormItem>
        <ElFormItem prop="authType" :label="$t('plugin.authType')">
          <ElSelect v-model="entity.authType">
            <ElOption
              v-for="item in authTypeList"
              :key="item.value"
              :label="item.label"
              :value="item.value || ''"
            />
          </ElSelect>
        </ElFormItem>
        <ElFormItem
          v-if="entity.authType === 'apiKey'"
          prop="position"
          :label="$t('plugin.position')"
        >
          <ElRadioGroup v-model="entity.position">
            <ElRadio value="headers">headers</ElRadio>
            <ElRadio value="query">query</ElRadio>
          </ElRadioGroup>
        </ElFormItem>
        <ElFormItem
          v-if="entity.authType === 'apiKey'"
          prop="tokenKey"
          :label="$t('plugin.tokenKey')"
        >
          <ElInput v-model.trim="entity.tokenKey" />
        </ElFormItem>
        <ElFormItem
          v-if="entity.authType === 'apiKey'"
          prop="tokenValue"
          :label="$t('plugin.tokenValue')"
        >
          <ElInput v-model.trim="entity.tokenValue" />
        </ElFormItem>
      </template>
    </ElForm>
  </EasyFlowFormModal>
</template>

<style scoped>
.headers-container-reduce {
  align-items: center;
}

.addHeadersBtn {
  width: 100%;
  margin-top: 8px;
  border-color: var(--el-color-primary);
  border-style: dashed;
  border-radius: 8px;
}

.head-con-content {
  align-items: center;
  margin-bottom: 8px;
}

.form-helper-text {
  margin-top: 6px;
  font-size: 12px;
  line-height: 18px;
  color: var(--el-text-color-secondary);
}
</style>
