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

import { computed, ref } from 'vue';

import { Position } from '@element-plus/icons-vue';
import { ElAlert, ElButton, ElForm, ElFormItem, ElMessage } from 'element-plus';

import { api } from '#/api/request';
import ShowJson from '#/components/json/ShowJson.vue';
import { $t } from '#/locales';
import WorkflowFormItem from '#/views/ai/workflow/components/WorkflowFormItem.vue';
import { buildSingleRunModel } from '../../../../../../packages/tinyflow-ui/src/utils/workflowNodeFields';

interface Props {
  workflowId: any;
  node: any;
}

const props = defineProps<Props>();

const singleRunForm = ref<FormInstance>();
const runParams = ref<any>({});
const submitLoading = ref(false);
const result = ref<any>('');
const singleRunModel = computed(() => buildSingleRunModel(props.node));
const isFieldMode = computed(() => singleRunModel.value.mode === 'fields');
const singleRunParameters = computed(() => singleRunModel.value.parameters);
const singleRunFields = computed(() => singleRunModel.value.fields);
const parameterDisplayNameMap = computed(() => {
  return new Map(
    singleRunParameters.value.map((parameter: any) => [
      String(parameter.name || ''),
      String(parameter.displayName || parameter.formLabel || parameter.name || ''),
    ]),
  );
});

function buildFieldSegments(value: string) {
  const source = String(value || '');
  const segments: Array<{ text: string; token: boolean }> = [];
  const regex = /\{\{\s*([^{}]+?)\s*}}/g;
  let lastIndex = 0;

  for (const match of source.matchAll(regex)) {
    const matchedText = match[0] || '';
    const tokenKey = String(match[1] || '').trim();
    const start = match.index ?? 0;
    if (start > lastIndex) {
      segments.push({
        text: source.slice(lastIndex, start),
        token: false,
      });
    }
    segments.push({
      text: parameterDisplayNameMap.value.get(tokenKey) || tokenKey,
      token: true,
    });
    lastIndex = start + matchedText.length;
  }

  if (lastIndex < source.length) {
    segments.push({
      text: source.slice(lastIndex),
      token: false,
    });
  }

  return segments.length > 0 ? segments : [{ text: '', token: false }];
}

function submit() {
  singleRunForm.value?.validate((valid) => {
    if (valid) {
      const params = {
        workflowId: props.workflowId,
        nodeId: props.node.id,
        variables: runParams.value,
      };
      submitLoading.value = true;
      api.post('/api/v1/workflow/singleRun', params).then((res) => {
        submitLoading.value = false;
        result.value = res.data;
        if (res.errorCode === 0) {
          ElMessage.success(res.message);
        } else {
          ElMessage.error(res.message);
        }
      });
    }
  });
}
</script>

<template>
  <div class="single-run">
    <ElForm
      class="single-run__form"
      label-position="top"
      ref="singleRunForm"
      :model="runParams"
    >
      <template v-if="isFieldMode">
        <div class="single-run-section">
          <div class="single-run-section__title">字段值</div>
          <ElAlert
            type="info"
            :closable="false"
            show-icon
            title="当前节点字段按正式配置展示；下方只需填写这些字段引用到的上游值。"
          />
          <div class="single-run-field-list">
            <div
              v-for="field in singleRunFields"
              :key="field.key"
              class="single-run-field-card"
            >
              <div class="single-run-field-card__label">
                {{ field.label }}
              </div>
              <div
                class="single-run-field-card__value"
                :class="{ 'is-multiline': field.multiline }"
              >
                <template v-if="field.value">
                  <template
                    v-for="(segment, index) in buildFieldSegments(field.value)"
                    :key="`${field.key}-${index}`"
                  >
                    <span
                      v-if="segment.token"
                      class="single-run-token-chip"
                    >
                      {{ segment.text }}
                    </span>
                    <span
                      v-else
                      class="single-run-field-card__text"
                    >
                      {{ segment.text }}
                    </span>
                  </template>
                </template>
                <span v-else class="single-run-field-card__placeholder">
                  {{ field.placeholder || '未设置' }}
                </span>
              </div>
            </div>
          </div>
        </div>

        <div class="single-run-section">
          <div class="single-run-section__title">上游引用</div>
          <ElAlert
            v-if="singleRunParameters.length === 0"
            type="success"
            :closable="false"
            show-icon
            title="当前字段没有引用上游参数，可直接运行。"
          />
          <WorkflowFormItem
            v-else
            v-model:run-params="runParams"
            :parameters="singleRunParameters"
          />
        </div>
      </template>
      <WorkflowFormItem
        v-else
        v-model:run-params="runParams"
        :parameters="singleRunParameters"
      />
      <ElFormItem>
        <ElButton
          type="primary"
          @click="submit"
          :loading="submitLoading"
          :icon="Position"
        >
          {{ $t('button.run') }}
        </ElButton>
      </ElFormItem>
    </ElForm>
    <section class="single-run-result">
      <div class="single-run-result__title">{{ $t('workflow.result') }}：</div>
      <ShowJson class="single-run-result__viewer" :value="result" />
    </section>
  </div>
</template>

<style scoped>
.single-run {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 100%;
}

.single-run__form {
  flex: 0 0 auto;
}

.single-run-result {
  display: flex;
  flex: 1;
  flex-direction: column;
  min-width: 0;
  min-height: 240px;
}

.single-run-result__title {
  margin: 10px 0;
  font-weight: 600;
}

.single-run-result__viewer {
  max-width: 100%;
  max-height: min(60vh, 720px);
  overflow: auto;
  overscroll-behavior: contain;
}

.single-run-section + .single-run-section {
  margin-top: 20px;
}

.single-run-section__title {
  margin-bottom: 10px;
  font-size: 13px;
  font-weight: 600;
  color: var(--el-text-color-primary);
}

.single-run-field-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-top: 12px;
}

.single-run-field-card {
  border: 1px solid var(--el-border-color-light);
  border-radius: 10px;
  padding: 12px;
  background: var(--el-fill-color-blank);
}

.single-run-field-card__label {
  margin-bottom: 8px;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.single-run-field-card__value {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  min-height: 20px;
  line-height: 1.7;
  color: var(--el-text-color-primary);
  white-space: nowrap;
}

.single-run-field-card__value.is-multiline {
  white-space: pre-wrap;
}

.single-run-field-card__text {
  white-space: inherit;
}

.single-run-field-card__placeholder {
  color: var(--el-text-color-placeholder);
}

.single-run-token-chip {
  display: inline-flex;
  align-items: center;
  max-width: 100%;
  padding: 1px 8px;
  border-radius: 999px;
  border: 1px solid var(--el-color-primary-light-5);
  background: var(--el-color-primary-light-9);
  color: var(--el-color-primary);
  font-size: 12px;
  line-height: 20px;
}
</style>
