<script setup>
import { ref, reactive, computed, watch } from 'vue'
import {
  NModal, NForm, NFormItem, NInput, NButton, NIcon, NSpin
} from 'naive-ui'
import { CloseOutline, CheckmarkCircleOutline, AlertCircleOutline } from '@vicons/ionicons5'
import { createGraphSource, updateGraphSource, testGraphSource } from '../../api/graphsource'

const props = defineProps({
  show: { type: Boolean, default: false },
  /** null 表示新增；非空表示编辑 */
  editing: { type: Object, default: null }
})
const emit = defineEmits(['update:show', 'saved'])

const visible = computed({
  get: () => props.show,
  set: v => emit('update:show', v)
})

const form = reactive({
  id: null,
  name: '',
  uri: 'bolt://localhost:7687',
  username: 'neo4j',
  passwordPlain: '',
  database: ''
})

const testing = ref(false)
const testResult = ref(null)  // {success, message}
const saving = ref(false)

watch(() => props.show, (v) => {
  if (v) {
    if (props.editing) {
      form.id = props.editing.id
      form.name = props.editing.name || ''
      form.uri = props.editing.uri || 'bolt://localhost:7687'
      form.username = props.editing.username || 'neo4j'
      form.passwordPlain = ''  // 编辑时密码留空表示不修改
      form.database = props.editing.database || ''
    } else {
      Object.assign(form, {
        id: null, name: '',
        uri: 'bolt://localhost:7687',
        username: 'neo4j',
        passwordPlain: '', database: ''
      })
    }
    testResult.value = null
  }
})

async function onTest() {
  if (!validateForm()) return
  testing.value = true
  testResult.value = null
  try {
    const res = await testGraphSource(buildPayload())
    testResult.value = res.data
  } catch (e) {
    testResult.value = { success: false, message: e.message }
  } finally {
    testing.value = false
  }
}

async function onSave() {
  if (!validateForm()) return
  saving.value = true
  try {
    if (form.id) {
      await updateGraphSource(form.id, buildPayload())
    } else {
      await createGraphSource(buildPayload())
    }
    visible.value = false
    emit('saved')
  } catch (e) {
    // 全局拦截器已弹消息
  } finally {
    saving.value = false
  }
}

function validateForm() {
  if (!form.name.trim()) return false
  if (!form.uri.trim()) return false
  if (!form.username.trim()) return false
  if (!form.id && !form.passwordPlain) return false
  return true
}

function buildPayload() {
  return {
    name: form.name.trim(),
    uri: form.uri.trim(),
    username: form.username.trim(),
    passwordPlain: form.passwordPlain || null,
    database: form.database.trim() || null
  }
}
</script>

<template>
  <n-modal
    :show="visible"
    @update:show="visible = $event"
    preset="card"
    style="max-width: 560px; width: 90vw"
    :bordered="false"
    :mask-closable="false"
  >
    <template #header>
      <div class="form-header">
        <span class="form-title">{{ form.id ? '编辑图谱源' : '新增图谱源' }}</span>
        <button class="icon-btn" @click="visible = false">
          <n-icon size="18"><CloseOutline /></n-icon>
        </button>
      </div>
    </template>

    <n-form label-placement="left" label-width="100" size="small">
      <n-form-item label="名称">
        <n-input v-model:value="form.name" placeholder="图谱源名称（唯一）" />
      </n-form-item>
      <n-form-item label="URI">
        <n-input v-model:value="form.uri" placeholder="bolt://host:7687 或 neo4j+s://host:7687" />
      </n-form-item>
      <n-form-item label="用户名">
        <n-input v-model:value="form.username" placeholder="neo4j" />
      </n-form-item>
      <n-form-item :label="form.id ? '新密码' : '密码'">
        <n-input
          v-model:value="form.passwordPlain"
          type="password"
          show-password-on="click"
          :placeholder="form.id ? '留空表示不修改' : '请输入密码'"
        />
      </n-form-item>
      <n-form-item label="Database">
        <n-input v-model:value="form.database" placeholder="可选，Enterprise 版数据库（Community 留空）" />
      </n-form-item>
    </n-form>

    <div class="hint">
      常见 URI：
      <code>bolt://localhost:7687</code>（单机）·
      <code>neo4j+s://xxx.databases.neo4j.io</code>（Aura TLS）
    </div>

    <div class="test-result" v-if="testResult">
      <div class="result-line" :class="{ success: testResult.success, error: !testResult.success }">
        <n-icon size="14">
          <CheckmarkCircleOutline v-if="testResult.success" />
          <AlertCircleOutline v-else />
        </n-icon>
        <span>{{ testResult.success ? '连接成功' : '连接失败' }}</span>
      </div>
      <div class="result-message" v-if="!testResult.success && testResult.message">
        {{ testResult.message }}
      </div>
    </div>

    <template #footer>
      <div class="form-footer">
        <n-button size="small" :loading="testing" @click="onTest">
          测试连接
        </n-button>
        <div class="footer-right">
          <n-button size="small" @click="visible = false">取消</n-button>
          <n-button
            size="small"
            type="primary"
            :loading="saving"
            :disabled="!validateForm()"
            @click="onSave"
          >
            {{ form.id ? '保存' : '创建' }}
          </n-button>
        </div>
      </div>
    </template>
  </n-modal>
</template>

<style scoped>
.form-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-right: 8px;
}
.form-title { font-size: 16px; font-weight: 600; color: var(--text-primary); }
.icon-btn {
  width: 32px; height: 32px;
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none;
  color: var(--text-secondary);
  cursor: pointer;
  border-radius: 6px;
}
.icon-btn:hover { color: var(--text-primary); background: rgba(255,255,255,0.08); }

.hint {
  margin-top: 4px;
  padding: 8px 10px;
  font-size: 11px;
  color: var(--text-muted);
  background: var(--bg-card);
  border: 1px dashed var(--border-color);
  border-radius: 4px;
}
.hint code {
  font-family: 'JetBrains Mono', monospace;
  color: var(--color-accent);
}

.test-result {
  margin-top: 8px;
  padding: 10px 12px;
  border-radius: 6px;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
}
.result-line {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  font-weight: 500;
}
.result-line.success { color: #10b981; }
.result-line.error { color: #ef4444; }
.result-message {
  margin-top: 6px;
  font-size: 12px;
  color: var(--text-secondary);
  font-family: monospace;
  word-break: break-all;
}

.form-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.footer-right { display: flex; gap: 8px; }
</style>
