<script setup lang="ts">
import { Bot, CheckCircle2, RotateCcw, ShieldCheck, Sparkles } from '@lucide/vue'
import { computed, ref, watch } from 'vue'

const props = defineProps<{
  content: string
  readOnly?: boolean
}>()

const emit = defineEmits<{
  apply: [content: string]
}>()

const startMarker = '<!-- NEXUS:STANDING_ORDERS:START -->'
const endMarker = '<!-- NEXUS:STANDING_ORDERS:END -->'
const goals = ref('')
const triggers = ref('')
const allowedActions = ref('')
const approvalBoundaries = ref('')
const escalation = ref('')
const verification = ref('')
const initializedFromContent = ref('')

const hasControlledSection = computed(() =>
  props.content.includes(startMarker) && props.content.includes(endMarker),
)

function bulletLines(value: string) {
  return value
    .split('\n')
    .map(line => line.trim().replace(/^[-*]\s*/, ''))
    .filter(Boolean)
}

function renderList(value: string) {
  const lines = bulletLines(value)
  return lines.length ? lines.map(line => `- ${line}`).join('\n') : '- Noch festzulegen'
}

function extractSection(source: string, title: string) {
  const escaped = title.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
  const match = source.match(new RegExp(`### ${escaped}\\s*\\n([\\s\\S]*?)(?=\\n### |$)`))
  if (!match) return ''
  return match[1]
    .split('\n')
    .map(line => line.trim())
    .filter(line => /^[-*]\s+/.test(line))
    .map(line => line.replace(/^[-*]\s+/, ''))
    .join('\n')
}

function hydrate() {
  if (initializedFromContent.value === props.content) return
  initializedFromContent.value = props.content
  const start = props.content.indexOf(startMarker)
  const end = props.content.indexOf(endMarker)
  if (start < 0 || end <= start) {
    goals.value = ''
    triggers.value = ''
    allowedActions.value = ''
    approvalBoundaries.value = ''
    escalation.value = ''
    verification.value = ''
    return
  }

  const block = props.content.slice(start + startMarker.length, end)
  goals.value = extractSection(block, 'Ziele')
  triggers.value = extractSection(block, 'Trigger')
  allowedActions.value = extractSection(block, 'Erlaubte Aktionen')
  approvalBoundaries.value = extractSection(block, 'Approval-Grenzen')
  escalation.value = extractSection(block, 'Eskalation')
  verification.value = extractSection(block, 'Verify und Report')
}

function buildBlock() {
  return [
    startMarker,
    '## Nexus Standing Orders',
    '',
    '> Von Nexus verwalteter, überprüfbarer Agent-First-Abschnitt. Änderungen gelten erst nach dem Speichern und bestätigten OpenClaw-Read-back.',
    '',
    '### Ziele',
    renderList(goals.value),
    '',
    '### Trigger',
    renderList(triggers.value),
    '',
    '### Erlaubte Aktionen',
    renderList(allowedActions.value),
    '',
    '### Approval-Grenzen',
    renderList(approvalBoundaries.value),
    '',
    '### Eskalation',
    renderList(escalation.value),
    '',
    '### Verify und Report',
    renderList(verification.value),
    endMarker,
  ].join('\n')
}

function apply() {
  const block = buildBlock()
  const start = props.content.indexOf(startMarker)
  const end = props.content.indexOf(endMarker)
  const next = start >= 0 && end > start
    ? `${props.content.slice(0, start)}${block}${props.content.slice(end + endMarker.length)}`
    : `${props.content.trimEnd()}\n\n${block}\n`
  emit('apply', next)
}

function reset() {
  initializedFromContent.value = ''
  hydrate()
}

watch(() => props.content, hydrate, { immediate: true })
</script>

<template>
  <section class="standing-orders" aria-labelledby="standing-orders-title">
    <header>
      <div>
        <span class="standing-orders__eyebrow">AGENT-FIRST CONTRACT</span>
        <h3 id="standing-orders-title">
          <Bot :size="17" aria-hidden="true" />
          Standing Orders
        </h3>
        <p>
          Nexus pflegt nur diesen markierten Abschnitt in <code>AGENTS.md</code>.
          Der übrige Agent-Inhalt bleibt unangetastet.
        </p>
      </div>
      <span class="standing-orders__state" :class="{ ready: hasControlledSection }">
        <CheckCircle2 v-if="hasControlledSection" :size="13" aria-hidden="true" />
        <Sparkles v-else :size="13" aria-hidden="true" />
        {{ hasControlledSection ? 'Vorhanden' : 'Neu' }}
      </span>
    </header>

    <div class="standing-orders__grid">
      <label>
        <span>Ziele</span>
        <textarea v-model="goals" rows="4" :disabled="readOnly" placeholder="Ein Ziel pro Zeile" />
      </label>
      <label>
        <span>Trigger</span>
        <textarea v-model="triggers" rows="4" :disabled="readOnly" placeholder="Wann der Agent selbstständig beginnt" />
      </label>
      <label>
        <span>Erlaubte Aktionen</span>
        <textarea v-model="allowedActions" rows="4" :disabled="readOnly" placeholder="Aktionen innerhalb des delegierten Scopes" />
      </label>
      <label>
        <span>Approval-Grenzen</span>
        <textarea v-model="approvalBoundaries" rows="4" :disabled="readOnly" placeholder="Was immer explizite Freigabe benötigt" />
      </label>
      <label>
        <span>Eskalation</span>
        <textarea v-model="escalation" rows="4" :disabled="readOnly" placeholder="Wann und an wen eskaliert wird" />
      </label>
      <label>
        <span>Verify und Report</span>
        <textarea v-model="verification" rows="4" :disabled="readOnly" placeholder="Pflichtprüfungen und Ergebnisformat" />
      </label>
    </div>

    <footer>
      <span>
        <ShieldCheck :size="14" aria-hidden="true" />
        Die Vorschau wird in den normalen, hash-geschützten Datei-Editor übernommen.
      </span>
      <div>
        <button type="button" class="nexus-button" :disabled="readOnly" @click="reset">
          <RotateCcw :size="13" aria-hidden="true" />
          Zurücksetzen
        </button>
        <button type="button" class="nexus-button nexus-button--primary" :disabled="readOnly" @click="apply">
          <Sparkles :size="13" aria-hidden="true" />
          In AGENTS.md übernehmen
        </button>
      </div>
    </footer>
  </section>
</template>

<style scoped>
.standing-orders {
  display: grid;
  gap: 13px;
  margin-top: 12px;
  padding: 15px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: linear-gradient(145deg, var(--glass), var(--accent-wash));
}

.standing-orders header,
.standing-orders footer,
.standing-orders footer > div {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  justify-content: space-between;
}

.standing-orders__eyebrow {
  display: block;
  margin-bottom: 4px;
  color: var(--a-purple);
  font: 10px var(--font-mono-v2);
  letter-spacing: .12em;
}

.standing-orders h3 {
  display: flex;
  gap: 7px;
  align-items: center;
  margin: 0;
  color: var(--tx);
  font: 700 15px var(--font-display);
}

.standing-orders header p {
  max-width: 630px;
  margin: 5px 0 0;
  color: var(--tx-2);
  font-size: 11px;
  line-height: 1.5;
}

.standing-orders code {
  font-family: var(--font-mono-v2);
}

.standing-orders__state {
  display: flex;
  gap: 5px;
  align-items: center;
  flex: 0 0 auto;
  padding: 5px 8px;
  border: 1px solid var(--line);
  border-radius: 999px;
  color: var(--tx-3);
  font: 10px var(--font-mono-v2);
}

.standing-orders__state.ready {
  border-color: var(--status-work-line);
  background: var(--status-work-bg);
  color: var(--st-work);
}

.standing-orders__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 9px;
}

.standing-orders label {
  display: grid;
  gap: 5px;
  min-width: 0;
}

.standing-orders label > span {
  color: var(--tx-2);
  font-size: 11px;
  font-weight: 700;
}

.standing-orders textarea {
  width: 100%;
  min-width: 0;
  resize: vertical;
  padding: 9px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  outline: 0;
  background: var(--field-surface);
  color: var(--tx);
  font: 11px/1.5 var(--font-body);
}

.standing-orders textarea:focus-visible {
  border-color: var(--a-blue);
  box-shadow: var(--focus-ring);
}

.standing-orders footer {
  align-items: center;
}

.standing-orders footer > span {
  display: flex;
  gap: 7px;
  align-items: center;
  color: var(--tx-3);
  font: 10px var(--font-mono-v2);
}

@media (max-width: 768px) {
  .standing-orders__grid {
    grid-template-columns: 1fr;
  }

  .standing-orders header,
  .standing-orders footer {
    align-items: stretch;
    flex-direction: column;
  }

  .standing-orders footer > div {
    justify-content: flex-start;
    flex-wrap: wrap;
  }
}
</style>
