<script setup lang="ts">
import { ref, watch } from 'vue';

import { ElInput, ElMessage, ElTable, ElTableColumn } from 'element-plus';

import { $t } from '#/locales';

const props = withDefaults(defineProps<Props>(), {
  modelValue: () => [],
  editable: false,
  isEditOutput: false,
  payloadMode: 'plugin',
});

const emit = defineEmits<Emits>();

export interface TreeTableNode {
  key: string;
  id?: string;
  name: string;
  description: string;
  method?: 'Body' | 'Header' | 'Path' | 'Query';
  required?: boolean;
  defaultValue?: string;
  enabled?: boolean;
  type?: string;
  children?: TreeTableNode[];
}

interface Props {
  modelValue?: TreeTableNode[];
  editable?: boolean;
  isEditOutput?: boolean;
  payloadMode?: 'plugin' | 'workflow';
}

const data = ref<TreeTableNode[]>([]);
const expandedKeys = ref<string[]>(['1']);
const errors = ref<
  Record<string, Partial<Record<keyof TreeTableNode, string>>>
>({});

watch(
  () => props.modelValue,
  (newVal) => {
    if (newVal) {
      data.value = newVal;
    }
  },
  { immediate: true, deep: true },
);

// 计算缩进宽度
const getNodeKey = (record?: Partial<TreeTableNode>): string => {
  return String(record?.key || record?.id || '');
};

const getIndentWidth = (record: TreeTableNode): number => {
  const level = getNodeKey(record).split('-').length - 1;
  const indentSize = 20;
  return level > 0 ? level * indentSize : 0;
};

// 数据变化处理
const handleDataChange = () => {
  emit('update:modelValue', data.value);
};

// 展开/折叠处理
const onExpand = (_row: TreeTableNode, expandedRows: TreeTableNode[]) => {
  expandedKeys.value = expandedRows.map((item) => item.key);
};

// 验证字段
const validatePluginFields = (): boolean => {
  const newErrors: Record<
    string,
    Partial<Record<keyof TreeTableNode, string>>
  > = {};
  let isValid = true;

  const checkNode = (node: TreeTableNode): boolean => {
    const { name, description, method, type } = node;
    const nodeErrors: Partial<Record<keyof TreeTableNode, string>> = {};
    const nodeKey = getNodeKey(node);

    if (!name?.trim()) {
      nodeErrors.name = $t('message.cannotBeEmpty.name');
      isValid = false;
    }

    if (!description?.trim()) {
      nodeErrors.description = $t('message.cannotBeEmpty.description');
      isValid = false;
    }

    if (isRootNode(node) && !method && !props.isEditOutput) {
      nodeErrors.method = $t('message.cannotBeEmpty.method');
      isValid = false;
    }

    if (!type) {
      nodeErrors.type = $t('message.cannotBeEmpty.type');
      isValid = false;
    }

    if (nodeKey && Object.keys(nodeErrors).length > 0) {
      newErrors[nodeKey] = nodeErrors;
    }

    if (node.children) {
      node.children.forEach((child) => {
        if (!checkNode(child)) isValid = false;
      });
    }

    return isValid;
  };

  data.value.forEach((node) => {
    if (!checkNode(node)) isValid = false;
  });

  errors.value = newErrors;
  return isValid;
};

const isBlankValue = (value: unknown): boolean => {
  if (value === null || value === undefined) {
    return true;
  }
  if (typeof value === 'string') {
    return value.trim().length === 0;
  }
  if (Array.isArray(value)) {
    return value.length === 0;
  }
  if (typeof value === 'object') {
    return Object.keys(value as Record<string, unknown>).length === 0;
  }
  return false;
};

const normalizeNodeType = (node: TreeTableNode): string => {
  return String(node.type || '').trim();
};

const parseWorkflowNodeValue = (node: TreeTableNode): any => {
  const type = normalizeNodeType(node);
  if (node.children?.length) {
    if (type === 'Object') {
      return buildWorkflowPayload(node.children);
    }
    if (type.includes('Array')) {
      return parseArrayValue(node);
    }
  }
  if (type.includes('Array')) {
    return parseArrayValue(node);
  }
  return node.defaultValue;
};

const parseArrayValue = (node: TreeTableNode): any[] => {
  const defaultValue = node.defaultValue as unknown;
  if (Array.isArray(defaultValue)) {
    return defaultValue;
  }
  const raw = String(defaultValue || '').trim();
  if (!raw) {
    return [];
  }
  try {
    const parsed = JSON.parse(raw);
    return Array.isArray(parsed) ? parsed : [parsed];
  } catch {
    return [raw];
  }
};

const buildWorkflowPayload = (nodes: TreeTableNode[]): Record<string, any> => {
  const payload: Record<string, any> = {};
  for (const node of nodes) {
    if (!node?.name) {
      continue;
    }
    payload[node.name] = parseWorkflowNodeValue(node);
  }
  return payload;
};

const validateWorkflowFields = (): boolean => {
  const newErrors: Record<
    string,
    Partial<Record<keyof TreeTableNode, string>>
  > = {};
  let isValid = true;

  const checkNode = (node: TreeTableNode) => {
    const nodeKey = getNodeKey(node);
    const nodeErrors: Partial<Record<keyof TreeTableNode, string>> = {};
    const value = parseWorkflowNodeValue(node);

    if (node.required && isBlankValue(value)) {
      nodeErrors.defaultValue = $t('message.required');
      isValid = false;
    }

    if (nodeKey && Object.keys(nodeErrors).length > 0) {
      newErrors[nodeKey] = nodeErrors;
    }

    node.children?.forEach(checkNode);
  };

  data.value.forEach((node) => {
    checkNode(node);
  });
  errors.value = newErrors;
  return isValid;
};

// 判断是否为根节点
const isRootNode = (record: TreeTableNode): boolean => {
  return !getNodeKey(record).includes('-');
};

// 提交参数
const handleSubmitParams = () => {
  const valid =
    props.payloadMode === 'workflow'
      ? validateWorkflowFields()
      : validatePluginFields();
  if (valid !== true) {
    ElMessage.error($t('message.completeForm'));
    return;
  }
  if (props.payloadMode === 'workflow') {
    return buildWorkflowPayload(data.value);
  }
  return data.value;
};

defineExpose({
  handleSubmitParams,
});

interface Emits {
  (e: 'update:modelValue', value: TreeTableNode[]): void;
  (e: 'submit', value: TreeTableNode[]): void;
}
</script>

<template>
  <div class="tree-table-container">
    <ElTable
      :data="data"
      :row-key="getNodeKey"
      :border="true"
      size="default"
      :expand-row-keys="expandedKeys"
      @expand-change="onExpand"
      style="width: 100%; overflow-x: auto"
    >
      <ElTableColumn
        prop="name"
        :label="$t('pluginItem.parameterName')"
        class-name="first-column"
      >
        <template #default="{ row }">
          <div class="name-cell">
            <div
              v-if="!props.editable || props.payloadMode === 'workflow'"
              :style="{ paddingLeft: `${getIndentWidth(row)}px` }"
            >
              {{ row.name || '' }}
            </div>
            <div v-else class="editable-name">
              <div class="name-input-wrapper">
                <div :style="{ width: `${getIndentWidth(row)}px` }"></div>
                <ElInput
                  v-model="row.name"
                  :disabled="row.name === 'arrayItem'"
                  @input="handleDataChange"
                />
              </div>
              <div
                v-if="errors[getNodeKey(row)]?.name"
                class="error-message"
                :style="{ marginLeft: `${getIndentWidth(row)}px` }"
              >
                {{ errors[getNodeKey(row)]?.name }}
              </div>
            </div>
          </div>
        </template>
      </ElTableColumn>

      <!-- 参数值-->
      <ElTableColumn
        prop="defaultValue"
        :label="$t('plugin.parameterValue')"
        width="150px"
      >
        <template #default="{ row }">
          <span v-if="row.type === 'Object'"></span>
          <span v-else-if="!props.editable">{{ row.defaultValue || '' }}</span>
          <div v-else class="value-input-wrapper">
            <ElInput
              v-model="row.defaultValue"
              @input="handleDataChange"
              :disabled="!props.editable"
            />
            <div
              v-if="errors[getNodeKey(row)]?.defaultValue"
              class="error-message"
            >
              {{ errors[getNodeKey(row)]?.defaultValue }}
            </div>
          </div>
        </template>
      </ElTableColumn>
    </ElTable>
  </div>
</template>

<style scoped>
.tree-table-container {
  box-sizing: border-box;
  width: 100%;
  overflow-x: auto;
}

.name-cell {
  position: relative;
  min-width: 100%;
}

.editable-name {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.name-input-wrapper {
  display: flex;
  align-items: center;
  width: 100%;
}

.name-input-wrapper .el-input {
  box-sizing: border-box;
  width: 100%;
}

.error-message {
  margin-top: 2px;
  font-size: 12px;
  line-height: 1.2;
  color: #ff4d4f;
}

.value-input-wrapper {
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.action-buttons .el-button {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  padding: 0;
}

:deep(.el-table td.el-table__cell.first-column div) {
  display: flex;
  gap: 2px;
  align-items: center;
}
</style>
