import { useState, useEffect } from 'react'
import { invoke as tauriInvoke } from '@tauri-apps/api/core'
import { isTauriHost } from '@/lib/api/desktop'
import { Input } from '@/components/ui/input'
import { Plus, Trash2 } from 'lucide-react'
type ExtractionRule = { trigger: string; memory_type: string; description: string }
type ContextRule = { scope: string; always_include: string[]; description: string }
type SuppressRule = { pattern: string; action: string; description: string }
type Rules = { extraction: ExtractionRule[]; context: ContextRule[]; suppress: SuppressRule[] }
export function RulesEditor() {
const [rules, setRules] = useState<Rules>({ extraction: [], context: [], suppress: [] })
const [saving, setSaving] = useState(false)
const [msg, setMsg] = useState('')
useEffect(() => {
if (!isTauriHost()) return
tauriInvoke<Rules>('desktop_get_rules').then(setRules).catch(() => {})
}, [])
async function handleSave() {
if (!isTauriHost()) return
setSaving(true)
setMsg('')
try {
await tauriInvoke('desktop_save_rules', { rules })
setMsg('已保存')
} catch (e) {
setMsg(`保存失败: ${e}`)
}
setSaving(false)
}
function addExtraction() {
setRules((prev) => ({
...prev,
extraction: [...prev.extraction, { trigger: '', memory_type: 'preference', description: '' }],
}))
}
function removeExtraction(idx: number) {
setRules((prev) => ({
...prev,
extraction: prev.extraction.filter((_, i) => i !== idx),
}))
}
function updateExtraction(idx: number, field: keyof ExtractionRule, value: string) {
setRules((prev) => ({
...prev,
extraction: prev.extraction.map((r, i) => (i === idx ? { ...r, [field]: value } : r)),
}))
}
function addSuppress() {
setRules((prev) => ({
...prev,
suppress: [...prev.suppress, { pattern: '', action: 'skip', description: '' }],
}))
}
function removeSuppress(idx: number) {
setRules((prev) => ({
...prev,
suppress: prev.suppress.filter((_, i) => i !== idx),
}))
}
function updateSuppress(idx: number, field: keyof SuppressRule, value: string) {
setRules((prev) => ({
...prev,
suppress: prev.suppress.map((r, i) => (i === idx ? { ...r, [field]: value } : r)),
}))
}
return (
<div className="space-y-4">
{/* 提炼规则 */}
<div>
<div className="flex items-center justify-between mb-2">
<h4 className="text-xs font-medium">提炼触发词</h4>
<button onClick={addExtraction} className="flex items-center gap-1 rounded border px-2 py-0.5 text-[10px] hover:bg-muted transition-colors">
<Plus className="h-3 w-3" /> 添加
</button>
</div>
<p className="text-[10px] text-muted-foreground mb-2">
当对话中出现这些触发词时,自动提炼为对应类型的记忆
</p>
{rules.extraction.map((rule, idx) => (
<div key={idx} className="flex items-center gap-2 mb-1.5">
<Input
value={rule.trigger}
onChange={(e) => updateExtraction(idx, 'trigger', e.target.value)}
placeholder="触发词"
className="text-xs h-7 flex-1"
/>
<select
value={rule.memory_type}
onChange={(e) => updateExtraction(idx, 'memory_type', e.target.value)}
className="h-7 rounded border bg-background px-2 text-xs"
>
<option value="preference">偏好</option>
<option value="decision">决策</option>
<option value="constraint">约束</option>
<option value="workflow">工作流</option>
<option value="incident">事件</option>
</select>
<button onClick={() => removeExtraction(idx)} className="p-1 text-muted-foreground hover:text-destructive">
<Trash2 className="h-3 w-3" />
</button>
</div>
))}
{rules.extraction.length === 0 && (
<p className="text-[10px] text-muted-foreground italic">暂无规则,点击添加</p>
)}
</div>
{/* 抑制规则 */}
<div>
<div className="flex items-center justify-between mb-2">
<h4 className="text-xs font-medium">抑制规则</h4>
<button onClick={addSuppress} className="flex items-center gap-1 rounded border px-2 py-0.5 text-[10px] hover:bg-muted transition-colors">
<Plus className="h-3 w-3" /> 添加
</button>
</div>
<p className="text-[10px] text-muted-foreground mb-2">
匹配这些模式的内容不会被提炼为记忆
</p>
{rules.suppress.map((rule, idx) => (
<div key={idx} className="flex items-center gap-2 mb-1.5">
<Input
value={rule.pattern}
onChange={(e) => updateSuppress(idx, 'pattern', e.target.value)}
placeholder="正则模式"
className="text-xs h-7 flex-1 font-mono"
/>
<button onClick={() => removeSuppress(idx)} className="p-1 text-muted-foreground hover:text-destructive">
<Trash2 className="h-3 w-3" />
</button>
</div>
))}
{rules.suppress.length === 0 && (
<p className="text-[10px] text-muted-foreground italic">暂无规则,点击添加</p>
)}
</div>
{/* 保存 */}
<div className="flex items-center gap-2 pt-2">
<button
onClick={handleSave}
disabled={saving}
className="rounded-md bg-primary px-3 py-1.5 text-xs text-primary-foreground hover:bg-primary/90 transition-colors disabled:opacity-50"
>
{saving ? '保存中...' : '保存规则'}
</button>
{msg && <span className="text-[10px] text-muted-foreground">{msg}</span>}
</div>
</div>
)
}