<script setup lang="ts">
import { ref, computed, onMounted } from "vue";
import { apiGet } from "@/api/client";
import DiffView from "@/components/DiffView.vue";
import type { DiffLine } from "@/composables/useAssist";

interface NoteVersion {
  id: number;
  note_id: number;
  title: string;
  tags: string[];
  body?: string;
  created_at: string;
}

const props = defineProps<{
  noteId: number;
  currentBody: string;
}>();

const emit = defineEmits<{
  (e: 'restore', body: string, tags: string[]): void;
  (e: 'close'): void;
}>();

const versions = ref<NoteVersion[]>([]);
const selectedVersion = ref<NoteVersion | null>(null);
const loading = ref(false);
const loadingDetail = ref(false);

const diff = computed<DiffLine[]>(() => {
  if (!selectedVersion.value?.body) return [];
  const a = props.currentBody;
  const b = selectedVersion.value.body;

  const aLines = a.split('\n');
  const bLines = b.split('\n');
  const m = aLines.length, n = bLines.length;
  const dp: number[][] = Array.from({ length: m + 1 }, () => new Array(n + 1).fill(0));
  for (let i = m - 1; i >= 0; i--)
    for (let j = n - 1; j >= 0; j--)
      dp[i][j] = aLines[i] === bLines[j]
        ? dp[i+1][j+1] + 1
        : Math.max(dp[i+1][j], dp[i][j+1]);
  const result: DiffLine[] = [];
  let i = 0, j = 0;
  while (i < m && j < n) {
    if (aLines[i] === bLines[j]) { result.push({ type: 'equal', text: aLines[i++] }); j++; }
    else if (dp[i+1][j] >= dp[i][j+1]) result.push({ type: 'delete', text: aLines[i++] });
    else result.push({ type: 'insert', text: bLines[j++] });
  }
  while (i < m) result.push({ type: 'delete', text: aLines[i++] });
  while (j < n) result.push({ type: 'insert', text: bLines[j++] });
  return result;
});

function formatDate(iso: string): string {
  const d = new Date(iso);
  return d.toLocaleString(undefined, {
    month: 'short', day: 'numeric', year: 'numeric',
    hour: '2-digit', minute: '2-digit',
  });
}

async function loadVersions() {
  loading.value = true;
  try {
    const data = await apiGet<{ versions: NoteVersion[] }>(
      `/api/notes/${props.noteId}/versions`
    );
    versions.value = data.versions;
    if (versions.value.length > 0) {
      await selectVersionItem(versions.value[0]);
    }
  } catch {
    // silent
  } finally {
    loading.value = false;
  }
}

async function selectVersionItem(v: NoteVersion) {
  if (v.body !== undefined) {
    selectedVersion.value = v;
    return;
  }
  loadingDetail.value = true;
  try {
    const full = await apiGet<NoteVersion>(
      `/api/notes/${props.noteId}/versions/${v.id}`
    );
    // Cache body back onto list item
    const listItem = versions.value.find(x => x.id === v.id);
    if (listItem) listItem.body = full.body;
    selectedVersion.value = full;
  } catch {
    // silent
  } finally {
    loadingDetail.value = false;
  }
}

function restore() {
  if (!selectedVersion.value?.body) return;
  emit('restore', selectedVersion.value.body, selectedVersion.value.tags ?? []);
}

onMounted(loadVersions);
</script>

<template>
  <teleport to="body">
    <div class="modal-overlay" @click.self="emit('close')">
      <div class="modal-card history-modal">
        <div class="history-header">
          <h3 class="history-title">Version History</h3>
          <button class="history-close" aria-label="Close version history" @click="emit('close')">&times;</button>
        </div>

        <div class="history-body">
          <!-- Left: version list -->
          <div class="history-list">
            <div v-if="loading" class="history-empty">Loading...</div>
            <div v-else-if="!versions.length" class="history-empty">No versions yet.</div>
            <div
              v-for="v in versions"
              :key="v.id"
              :class="['history-item', { selected: selectedVersion?.id === v.id }]"
              @click="selectVersionItem(v)"
            >
              <div class="history-item-title">{{ v.title || 'Untitled' }}</div>
              <div class="history-item-date">{{ formatDate(v.created_at) }}</div>
            </div>
          </div>

          <!-- Right: diff -->
          <div class="history-diff">
            <div v-if="loadingDetail" class="history-empty">Loading version...</div>
            <div v-else-if="!selectedVersion" class="history-empty">Select a version to compare.</div>
            <DiffView v-else :diff="diff" />
          </div>
        </div>

        <div class="history-footer">
          <button
            class="btn-restore"
            :disabled="!selectedVersion?.body"
            @click="restore"
          >Restore this version</button>
          <button class="modal-btn" @click="emit('close')">Close</button>
        </div>
      </div>
    </div>
  </teleport>
</template>

<style scoped>
.history-modal {
  max-width: 900px;
  width: 95%;
  height: 80vh;
  max-height: 700px;
  display: flex;
  flex-direction: column;
  padding: 0;
}

.history-header {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.9rem 1.25rem;
  border-bottom: 1px solid var(--color-border);
}

.history-title {
  margin: 0;
  font-size: 1rem;
}

.history-close {
  background: none;
  border: none;
  font-size: 1.25rem;
  cursor: pointer;
  color: var(--color-text-muted);
  line-height: 1;
  padding: 0.1rem 0.3rem;
}
.history-close:hover { color: var(--color-text); }

.history-body {
  flex: 1;
  min-height: 0;
  display: flex;
  overflow: hidden;
}

.history-list {
  width: 220px;
  flex-shrink: 0;
  border-right: 1px solid var(--color-border);
  overflow-y: auto;
}

.history-item {
  padding: 0.6rem 0.9rem;
  cursor: pointer;
  border-left: 3px solid transparent;
  border-bottom: 1px solid var(--color-border);
}
.history-item:hover { background: var(--color-bg-secondary); }
.history-item.selected {
  border-left-color: var(--color-primary);
  background: var(--color-bg-secondary);
}

.history-item-title {
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--color-text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.history-item-date {
  font-size: 0.75rem;
  color: var(--color-text-muted);
  margin-top: 0.15rem;
}

.history-diff {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  padding: 0.5rem;
}

.history-empty {
  padding: 1rem;
  font-size: 0.85rem;
  color: var(--color-text-muted);
}

.history-footer {
  flex-shrink: 0;
  display: flex;
  gap: 0.5rem;
  justify-content: flex-end;
  padding: 0.75rem 1.25rem;
  border-top: 1px solid var(--color-border);
}

.btn-restore {
  padding: 0.45rem 1rem;
  background: var(--color-primary);
  color: #fff;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  font-size: 0.9rem;
}
.btn-restore:disabled {
  opacity: 0.5;
  cursor: default;
}
</style>
