<script setup>
// 启动台「保存为应用」表单弹窗：从 Launchpad 抽出，供启动台与端口监控复用。
// props.initial 非空即打开；带 _suggest 时用其作为启停命令建议（来自项目草稿）。
import { ref, watch } from 'vue'
import { useI18n } from 'vue-i18n'
import { Rocket, X, FolderOpen, Image, ImageUp, Hexagon, Zap, FileCode2, Coffee, Database, Globe, Boxes, Box } from 'lucide-vue-next'
import { call } from '../api'

const props = defineProps({
  initial: { type: Object, default: null },
  initialError: { type: String, default: '' }
})
const emit = defineEmits(['close', 'saved'])
const { t } = useI18n()

const KINDS = ['node', 'go', 'python', 'java', 'php', 'dotnet', 'exe', 'mysql', 'redis', 'nginx', 'web', 'other']
const CAT_PRESETS = ['前端', '后端', '数据库', '工具', '桌面', '其他']
const KIND_UI = {
  node: { icon: Hexagon, color: '#8cc84b' },
  go: { icon: Zap, color: '#00add8' },
  python: { icon: FileCode2, color: '#ffd343' },
  java: { icon: Coffee, color: '#f89820' },
  php: { icon: FileCode2, color: '#a78bfa' },
  dotnet: { icon: Boxes, color: '#8b5cf6' },
  exe: { icon: Box, color: '#60a5fa' },
  mysql: { icon: Database, color: '#4f9df5' },
  redis: { icon: Database, color: '#f16a5b' },
  nginx: { icon: Globe, color: '#26c795' },
  web: { icon: Globe, color: '#4f9df5' },
  other: { icon: Box, color: 'var(--muted)' }
}
const kindUI = k => KIND_UI[k] || KIND_UI.other

const form = ref(null)
const suggest = ref({ start: [], stop: [] })
const err = ref('')
const primaryCats = ref([])
const kindIcons = ref({})
let metaLoaded = false

async function loadMeta() {
  if (metaLoaded) return
  metaLoaded = true
  try { primaryCats.value = await call('ListLaunchCategories') || [] } catch { primaryCats.value = [] }
  try { kindIcons.value = await call('ListKindIcons') || {} } catch { kindIcons.value = {} }
}

watch(() => props.initial, async x => {
  if (!x) { form.value = null; return }
  err.value = ''
  form.value = {
    id: x.id || 0,
    name: x.name || '',
    kind: x.kind || 'other',
    port: x.port || 0,
    dir: x.dir || '',
    startCmd: x.startCmd || '',
    stopCmd: x.stopCmd || '',
    icon: x.icon || '',
    categoryId: x.categoryId || 0,
    category: x.category || ''
  }
  loadMeta()
  if (x._suggest) {
    suggest.value = { start: x._suggest.start || [], stop: x._suggest.stop || [] }
    peekIcon()
  } else if (form.value.dir && !form.value.startCmd) {
    await detectDir(false)
  } else {
    await loadSuggest()
  }
}, { immediate: true })

async function loadSuggest() {
  try { suggest.value = await call('LaunchCmdSuggest', form.value.kind) } catch { suggest.value = { start: [], stop: [] } }
}
async function detectDir(overwrite = true) {
  if (!form.value?.dir) return
  try {
    const p = await call('DetectLaunchProfile', form.value.dir)
    if (!p) return
    if (overwrite || !form.value.name) form.value.name = p.name || form.value.name
    if (overwrite || !form.value.kind || form.value.kind === 'other') form.value.kind = p.kind || form.value.kind
    if (overwrite || !form.value.port) form.value.port = p.port || form.value.port
    if (overwrite || !form.value.startCmd) form.value.startCmd = p.startCmd || form.value.startCmd
    suggest.value = { start: p.start || [], stop: p.stop || [] }
    if (!suggest.value.start?.length) await loadSuggest()
  } catch { await loadSuggest() }
}
async function pickDir() {
  try {
    const d = await call('SelectDirectory')
    if (d) {
      form.value.dir = d
      await detectDir(true)
    }
  } catch { /* 用户取消 */ }
}
async function peekIcon() {
  if (!form.value) return
  try {
    form.value.icon = await call('PeekLaunchIcon', Number(form.value.port) || 0, form.value.dir || '')
  } catch { /* ignore */ }
}
async function pickLocalIcon() {
  if (!form.value) return
  try {
    const u = await call('PickLaunchIconImage')
    if (u) form.value.icon = u
  } catch (e) { err.value = String(e?.message || e) }
}
async function save() {
  err.value = ''
  try {
    const saved = await call('SaveLaunchApp', {
      ...form.value,
      port: Number(form.value.port) || 0,
      categoryId: Number(form.value.categoryId) || 0
    })
    emit('saved', saved)
  } catch (e) {
    err.value = String(e?.message || e)
  }
}
</script>

<template>
  <Teleport to="body">
    <div v-if="form" class="overlay" @click.self="emit('close')">
      <section class="modal lp-modal">
        <header class="lp-modal-head">
          <h2><Rocket />{{ form.id ? t('lpEditApp') : t('lpAddApp') }}</h2>
          <button type="button" class="nm-close" :title="t('close')" @click="emit('close')"><X /></button>
        </header>
        <div class="lp-form">
          <div class="lp-icon-edit">
            <span class="lp-icon lg" :style="{ color: kindUI(form.kind).color, background: `color-mix(in srgb, ${kindUI(form.kind).color} 14%, transparent)` }">
              <img v-if="form.icon || kindIcons[form.kind]" :src="form.icon || kindIcons[form.kind]" alt="" />
              <component v-else :is="kindUI(form.kind).icon" />
            </span>
            <div class="lp-icon-btns">
              <button type="button" class="btn secondary" @click="pickLocalIcon"><ImageUp />{{ t('lpPickIcon') }}</button>
              <button type="button" class="btn secondary" @click="peekIcon"><Image />{{ t('lpFetchIcon') }}</button>
              <button v-if="form.icon" type="button" class="btn secondary" @click="form.icon = ''"><X />{{ t('lpClearIcon') }}</button>
            </div>
          </div>
          <label class="lp-field"><span>{{ t('lpName') }}</span><input v-model="form.name" :placeholder="t('lpName')" /></label>
          <label class="lp-field"><span>{{ t('lpPrimaryCat') }}</span>
            <select v-model.number="form.categoryId">
              <option :value="0">{{ t('lpCatNone') }}</option>
              <option v-for="c in primaryCats" :key="c.id" :value="c.id">{{ c.name }}</option>
            </select>
          </label>
          <label class="lp-field"><span>{{ t('lpSecondaryCat') }}</span>
            <input v-model.trim="form.category" list="lafm-cat-list" :placeholder="t('lpCategoryPh')" />
            <datalist id="lafm-cat-list"><option v-for="c in CAT_PRESETS" :key="c" :value="c" /></datalist>
          </label>
          <div class="lp-row">
            <label class="lp-field"><span>{{ t('lpKind') }}</span>
              <select v-model="form.kind" @change="loadSuggest">
                <option v-for="k in KINDS" :key="k" :value="k">{{ k }}</option>
              </select>
            </label>
            <label class="lp-field"><span>{{ t('lpPort') }}</span><input v-model="form.port" type="number" min="0" max="65535" /></label>
          </div>
          <label class="lp-field"><span>{{ t('lpDir') }}</span>
            <span class="lp-dir-row"><input v-model="form.dir" :placeholder="t('lpDir')" @change="detectDir(true)" /><button type="button" class="btn secondary" @click="pickDir"><FolderOpen /></button></span>
          </label>
          <label class="lp-field"><span>{{ t('lpStartCmd') }}</span><input v-model="form.startCmd" placeholder="npm run dev" /></label>
          <div v-if="suggest.start?.length" class="lp-suggest">
            <small>{{ t('lpSuggest') }}</small>
            <button v-for="c in suggest.start" :key="c" type="button" @click="form.startCmd = c">{{ c }}</button>
          </div>
          <label class="lp-field"><span>{{ t('lpStopCmd') }}</span><input v-model="form.stopCmd" :placeholder="t('lpStopBlank')" /></label>
          <div v-if="suggest.stop?.length" class="lp-suggest">
            <small>{{ t('lpSuggest') }}</small>
            <button v-for="c in suggest.stop" :key="c" type="button" @click="form.stopCmd = c">{{ c }}</button>
          </div>
          <p v-if="err || initialError" class="lp-err">{{ err || initialError }}</p>
        </div>
        <footer class="lp-modal-foot">
          <button class="btn secondary" @click="emit('close')">{{ t('cancel') }}</button>
          <button class="btn" @click="save">{{ t('save') }}</button>
        </footer>
      </section>
    </div>
  </Teleport>
</template>
