<script setup lang="ts">
// <!-- ld-v2 --> Diff inline +/− entre la version courante et une version
// proposée — contenu d'abord, calculé localement (LCS ligne à ligne, sans lib).
const props = defineProps<{
  current: string
  proposed: string
}>()

interface DiffLine {
  text: string
  type: 'kept' | 'removed' | 'added'
}

/** Line-based LCS diff — texts are clause-sized, the DP table stays tiny. */
function lineDiff(a: string[], b: string[]): DiffLine[] {
  const n = a.length
  const m = b.length
  // lcs[i][j] = LCS length of a[i:] / b[j:]
  const lcs: number[][] = Array.from({ length: n + 1 }, () => new Array<number>(m + 1).fill(0))
  for (let i = n - 1; i >= 0; i--) {
    for (let j = m - 1; j >= 0; j--) {
      lcs[i]![j] = a[i] === b[j]
        ? lcs[i + 1]![j + 1]! + 1
        : Math.max(lcs[i + 1]![j]!, lcs[i]![j + 1]!)
    }
  }
  const out: DiffLine[] = []
  let i = 0
  let j = 0
  while (i < n && j < m) {
    if (a[i] === b[j]) {
      out.push({ text: a[i]!, type: 'kept' })
      i++
      j++
    } else if (lcs[i + 1]![j]! >= lcs[i]![j + 1]!) {
      out.push({ text: a[i]!, type: 'removed' })
      i++
    } else {
      out.push({ text: b[j]!, type: 'added' })
      j++
    }
  }
  while (i < n) out.push({ text: a[i++]!, type: 'removed' })
  while (j < m) out.push({ text: b[j++]!, type: 'added' })
  return out
}

const lines = computed(() => {
  const a = props.current.split('\n')
  const b = props.proposed.split('\n')
  return lineDiff(a, b).filter(l => !(l.type === 'kept' && l.text.trim() === ''))
})

const changedCount = computed(() => lines.value.filter(l => l.type !== 'kept').length)
</script>

<template>
  <!-- ld-v2 -->
  <div class="clause-diff">
    <div v-if="changedCount === 0" class="clause-diff__same">
      Aucun changement de texte — les deux versions sont identiques.
    </div>
    <div
      v-for="(line, index) in lines"
      v-else
      :key="index"
      class="clause-diff__line"
      :class="`clause-diff__line--${line.type}`"
    >
      <span class="clause-diff__marker" aria-hidden="true">
        {{ line.type === 'added' ? '+' : line.type === 'removed' ? '−' : '' }}
      </span>
      <span class="clause-diff__text">{{ line.text }}</span>
    </div>
  </div>
</template>

<style scoped>
.clause-diff {
  border-radius: var(--r-input);
  overflow: hidden;
  background: color-mix(in srgb, var(--mood-text) 3%, var(--mood-surface));
  font-size: 0.8125rem;
  line-height: 1.55;
}
.clause-diff__same {
  padding: 0.6rem 0.9rem;
  color: var(--mood-text-muted);
  font-style: italic;
}
.clause-diff__line {
  display: flex;
  gap: 0.5rem;
  padding: 0.15rem 0.9rem;
}
.clause-diff__line--removed {
  background: color-mix(in srgb, var(--mood-error) 10%, transparent);
  color: color-mix(in srgb, var(--mood-error) 80%, var(--mood-text));
  text-decoration: line-through;
  text-decoration-thickness: 1px;
}
.clause-diff__line--added {
  background: color-mix(in srgb, var(--mood-success) 11%, transparent);
  color: color-mix(in srgb, var(--mood-success) 75%, var(--mood-text));
}
.clause-diff__marker {
  flex-shrink: 0;
  width: 0.9rem;
  font-weight: 800;
  font-family: monospace;
  text-align: center;
}
.clause-diff__text { white-space: pre-wrap; word-break: break-word; }
</style>
