<script setup lang="ts">
const props = defineProps({
  tool: { type: Object as PropType<any>, required: true },
})

const emit = defineEmits(["close"])

const { $toast } = useNuxtApp()

const inputText = ref("")
const resultText = ref("")
const executing = ref(false)
const resultOk = ref<boolean | null>(null)

const { data: typesData } = await useHttpFetch("/api/agent-tools/types")
const typeMetaList = computed(() => (typesData.value as any[]) ?? [])
const inputSchema = computed(() => {
  const meta = typeMetaList.value.find((m: any) => m.type === props.tool?.type)
  return meta?.inputSchema ?? {}
})

const schemaHint = computed(() => {
  const props_ = inputSchema.value?.properties ?? {}
  const required: string[] = inputSchema.value?.required ?? []
  const fields = Object.entries(props_).map(([k, v]: [string, any]) => {
    const req = required.includes(k) ? " (必填)" : ""
    const desc = v.description ? ` — ${v.description}` : ""
    return `${k}: ${v.type ?? "any"}${req}${desc}`
  })
  return fields.length ? fields.join("\n") : "无字段定义"
})

const defaultInput = computed(() => {
  const props_ = inputSchema.value?.properties ?? {}
  const obj: Record<string, any> = {}
  for (const [k, v] of Object.entries(props_)) {
    if ((v as any).type === "string") obj[k] = ""
    else if ((v as any).type === "number") obj[k] = 0
    else obj[k] = null
  }
  return JSON.stringify(obj, null, 2)
})

onMounted(() => {
  inputText.value = defaultInput.value
})

async function execute() {
  executing.value = true
  resultText.value = ""
  resultOk.value = null

  let parsedInput: any
  try {
    parsedInput = JSON.parse(inputText.value)
  } catch {
    resultText.value = "输入不是合法 JSON"
    resultOk.value = false
    executing.value = false
    return
  }

  try {
    const res: any = await $fetch(`/api/agent-tools/${props.tool.id}/execute`, {
      method: "POST",
      body: { input: parsedInput },
    })
    const data = res?.data ?? res
    resultText.value = JSON.stringify(data, null, 2)
    resultOk.value = data?.ok !== false
    if (data?.ok !== false) $toast.success("执行成功")
    else $toast.error("执行失败")
  } catch (err: any) {
    resultText.value = err?.data?.message ?? err?.message ?? "执行失败"
    resultOk.value = false
    $toast.error("执行失败")
  } finally {
    executing.value = false
  }
}

function onOverlayClick(e: MouseEvent) {
  if ((e.target as HTMLElement).dataset.overlay === "true") {
    emit("close")
  }
}
</script>

<template>
  <div data-overlay="true" class="modal-overlay" @click="onOverlayClick">
    <div class="modal-container">
      <div class="modal-header">
        <h2 class="modal-title">测试工具 — {{ tool.name }}</h2>
        <button class="modal-close-btn" @click="emit('close')">
          <svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
            <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
          </svg>
        </button>
      </div>

      <div class="modal-body">
        <div class="schema-hint">
          <div class="hint-label">输入参数说明：</div>
          <pre class="hint-content">{{ schemaHint }}</pre>
        </div>

        <div class="form-group">
          <label class="form-label">输入 (JSON)</label>
          <textarea v-model="inputText" rows="6" class="form-textarea form-input-mono"></textarea>
        </div>

        <div class="form-group">
          <label class="form-label">结果</label>
          <pre :class="['result-area', resultOk === true ? 'result-ok' : resultOk === false ? 'result-err' : '']">{{ resultText || '点击执行后显示结果...' }}</pre>
        </div>
      </div>

      <div class="modal-footer">
        <button class="btn-secondary" @click="emit('close')">关闭</button>
        <button :disabled="executing" class="btn-primary" @click="execute">
          {{ executing ? '执行中...' : '执行' }}
        </button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 50;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding-top: 8vh;
  background: rgba(20, 20, 19, 0.4);
}

.modal-container {
  background: var(--color-canvas);
  border-radius: 12px;
  box-shadow: 0 20px 40px rgba(20, 20, 19, 0.2);
  width: 100%;
  max-width: 640px;
  max-height: 84vh;
  overflow-y: auto;
}

.modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px;
  border-bottom: 1px solid var(--color-hairline);
}

.modal-title {
  font-size: 18px;
  font-weight: 500;
  color: var(--color-ink);
  margin: 0;
}

.modal-close-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border: none;
  background: transparent;
  border-radius: 6px;
  color: var(--color-muted);
  cursor: pointer;
  transition: all 0.15s ease;
}

.modal-close-btn:hover {
  background: var(--color-surface-soft);
  color: var(--color-ink);
}

.modal-body {
  padding: 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.schema-hint {
  padding: 12px 16px;
  background: var(--color-surface-soft);
  border-radius: 8px;
  border: 1px solid var(--color-hairline);
}

.hint-label {
  font-size: 13px;
  font-weight: 500;
  color: var(--color-muted);
  margin-bottom: 6px;
}

.hint-content {
  font-family: 'JetBrains Mono', monospace;
  font-size: 12px;
  color: var(--color-body-strong);
  white-space: pre-wrap;
  margin: 0;
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.form-label {
  font-size: 14px;
  font-weight: 500;
  color: var(--color-body-strong);
}

.form-textarea {
  width: 100%;
  padding: 10px 14px;
  font-size: 14px;
  color: var(--color-ink);
  background: var(--color-canvas);
  border: 1px solid var(--color-hairline);
  border-radius: 8px;
  transition: all 0.15s ease;
  resize: vertical;
  min-height: 80px;
}

.form-textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px rgba(204, 120, 92, 0.15);
}

.form-input-mono {
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
}

.result-area {
  width: 100%;
  min-height: 120px;
  max-height: 300px;
  overflow-y: auto;
  padding: 12px 14px;
  font-family: 'JetBrains Mono', monospace;
  font-size: 13px;
  color: var(--color-body-strong);
  background: var(--color-surface-soft);
  border: 1px solid var(--color-hairline);
  border-radius: 8px;
  white-space: pre-wrap;
  word-break: break-all;
  margin: 0;
}

.result-ok {
  border-color: #137333;
  background: #f0f9f3;
}

.result-err {
  border-color: #c64545;
  background: #fef0f0;
}

.modal-footer {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 16px 24px;
  border-top: 1px solid var(--color-hairline);
  background: var(--color-surface-soft);
  border-radius: 0 0 12px 12px;
}

.btn-secondary {
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-body-strong);
  background: var(--color-canvas);
  border: 1px solid var(--color-hairline);
  border-radius: 8px;
  cursor: pointer;
  transition: all 0.15s ease;
}

.btn-secondary:hover {
  background: var(--color-surface-soft);
}

.btn-primary {
  padding: 10px 16px;
  font-size: 14px;
  font-weight: 500;
  color: var(--color-on-primary);
  background: var(--color-primary);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  transition: background 0.15s ease;
}

.btn-primary:hover {
  background: var(--color-primary-active);
}

.btn-primary:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}
</style>
