<template>
  <div class="versioning-dialog" @click.self="$emit('close')">
    <div class="versioning-card">
      <header class="versioning-header">
        <div class="versioning-header-left">
          <h3>版本管理</h3>
          <label class="switch-line">
            <input
              type="checkbox"
              :checked="enabled"
              :disabled="loading"
              @change="$emit('toggle-enabled', ($event.target as HTMLInputElement).checked)"
            />
            <span>开启</span>
          </label>
          <label class="scope-line">
            <span>管理范围</span>
            <select
              :value="trackingMode"
              :disabled="!hostMode || loading || restoring"
              @change="$emit('update:tracking-mode', ($event.target as HTMLSelectElement).value)"
            >
              <option value="workspace_and_conversation" :disabled="!hostMode">
                管理工作区和对话
              </option>
              <option value="conversation_only">仅管理对话</option>
            </select>
          </label>
        </div>
        <div class="versioning-header-actions">
          <button type="button" class="refresh-btn" :disabled="loading" @click="$emit('refresh')">
            刷新
          </button>
          <button type="button" class="close-btn" @click="$emit('close')">×</button>
        </div>
      </header>

      <div class="versioning-body">
        <aside class="checkpoint-list">
          <div
            v-for="item in orderedItems"
            :key="item.seq"
            class="checkpoint-item"
            :class="{ active: Number(selectedSeq) === Number(item.seq) }"
            @click="$emit('select', item.seq)"
          >
            <div class="row top">
              <span class="seq">#{{ item.seq }}</span>
              <span class="time">{{ formatTime(item.timestamp) }}</span>
            </div>
            <div class="preview">{{ item.message_preview || '(空消息)' }}</div>
            <div class="row stats">
              <span class="plus">+{{ item.insertions || 0 }}</span>
              <span class="minus">-{{ item.deletions || 0 }}</span>
              <span class="files">{{ item.files_changed || 0 }} 文件</span>
            </div>
          </div>
          <div v-if="!items.length" class="empty">暂无版本点</div>
        </aside>

        <section class="checkpoint-detail">
          <div v-if="detailLoading" class="loading">加载详情中...</div>
          <template v-else-if="detail">
            <h4>提交详情 #{{ detail.seq }}</h4>
            <div class="summary">
              <span class="plus">+{{ detail.insertions || 0 }}</span>
              <span class="minus">-{{ detail.deletions || 0 }}</span>
              <span>{{ detail.files_changed || 0 }} 文件</span>
            </div>
            <div class="files">
              <template v-for="(file, idx) in detail.files || []" :key="`${file.status}:${file.path}:${idx}`">
                <div class="file-row" :class="{ expanded: isFileExpanded(file, idx) }" @click="toggleFileExpand(file, idx)">
                  <span class="status">{{ file.status }}</span>
                  <span class="path">{{ file.path }}</span>
                  <span class="delta">
                    <span class="plus">+{{ file.insertions || 0 }}</span>
                    <span class="minus">-{{ file.deletions || 0 }}</span>
                  </span>
                </div>
                <div v-if="isFileExpanded(file, idx)" class="tool-result-diff scrollable versioning-diff">
                  <div v-if="!(file.patch_lines || []).length" class="empty">暂无可展示的文本变更行</div>
                  <div
                    v-for="(line, lineIdx) in file.patch_lines || []"
                    :key="`line:${idx}:${lineIdx}`"
                    class="diff-line"
                    :class="line.type === 'add' ? 'diff-add' : (line.type === 'remove' ? 'diff-remove' : 'diff-context')"
                  >
                    {{ line.type === 'add' ? '+ ' : (line.type === 'remove' ? '- ' : '  ') }}{{ line.content }}
                  </div>
                  <div v-if="file.patch_truncated" class="approval-note">内容过长，已截断展示</div>
                </div>
              </template>
            </div>
          </template>
          <div v-else class="empty">请选择一个版本点查看详情</div>
        </section>
      </div>

      <footer class="versioning-footer">
        <div v-if="needWorkspaceMatch && workspaceMatched === false" class="workspace-mismatch-tip">
          当前对话所属工作区与当前工作区不一致，无法执行回溯。
        </div>
        <label>回溯模式：覆盖当前对话</label>
        <button
          type="button"
          class="confirm-btn"
          :disabled="!enabled || selectedSeq === null || selectedSeq === undefined || restoring || (needWorkspaceMatch && workspaceMatched === false)"
          @click="$emit('confirm')"
        >
          {{ restoring ? '回溯中...' : '确认回溯' }}
        </button>
      </footer>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';

const props = defineProps<{
  hostMode: boolean;
  enabled: boolean;
  trackingMode: string;
  loading: boolean;
  items: any[];
  selectedSeq: number | null;
  detail: any;
  detailLoading: boolean;
  restoring: boolean;
  restoreMode: string;
  workspaceMatched?: boolean;
}>();

defineEmits([
  'close',
  'refresh',
  'toggle-enabled',
  'update:tracking-mode',
  'select',
  'confirm',
  'update:restore-mode'
]);

const needWorkspaceMatch = computed(() => String(props.trackingMode || '') !== 'conversation_only');

const orderedItems = computed(() => {
  const src = Array.isArray(props.items) ? props.items : [];
  return [...src].sort((a: any, b: any) => Number(a?.seq || 0) - Number(b?.seq || 0));
});

const expandedFileKey = ref<string | null>(null);
const fileKey = (file: any, idx: number) => `${file?.status || ''}:${file?.old_path || ''}:${file?.path || ''}:${idx}`;
const toggleFileExpand = (file: any, idx: number) => {
  const key = fileKey(file, idx);
  expandedFileKey.value = expandedFileKey.value === key ? null : key;
};
const isFileExpanded = (file: any, idx: number) => expandedFileKey.value === fileKey(file, idx);

watch(
  () => props.detail?.seq,
  () => {
    expandedFileKey.value = null;
  }
);

const formatTime = (value: string) => {
  if (!value) return '-';
  try {
    return new Date(value).toLocaleString('zh-CN', {
      month: '2-digit',
      day: '2-digit',
      hour: '2-digit',
      minute: '2-digit'
    });
  } catch {
    return value;
  }
};
</script>

<style scoped>
.versioning-dialog { position: fixed; inset: 0; z-index: 1200; background: var(--theme-overlay-scrim); display: flex; align-items: center; justify-content: center; padding: 20px; backdrop-filter: blur(8px); }
.versioning-card { width: min(1120px, 96vw); height: 600px; overflow: hidden; border-radius: 14px; background: var(--theme-surface-card); border: 1px solid var(--theme-control-border); box-shadow: var(--theme-shadow-strong); display: flex; flex-direction: column; color: var(--claude-text); }
.versioning-header { padding: 14px 18px; border-bottom: 1px solid var(--theme-control-border); display: flex; align-items: center; justify-content: space-between; gap: 12px; }
.versioning-header-left { display: inline-flex; align-items: center; gap: 14px; min-width: 0; }
.versioning-header-actions { display: inline-flex; align-items: center; gap: 8px; }
.close-btn { border: 0; background: transparent; font-size: 24px; cursor: pointer; }
.switch-line { display: flex; align-items: center; gap: 8px; font-size: 14px; }
.scope-line { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--claude-text-secondary); }
.scope-line select { border: 1px solid var(--theme-control-border); border-radius: 8px; padding: 5px 10px; background: var(--theme-surface-soft); color: var(--claude-text); }
.refresh-btn { border: 1px solid var(--theme-control-border); border-radius: 8px; padding: 6px 10px; background: var(--theme-surface-soft); color: var(--claude-text); cursor: pointer; }
.versioning-body { display: grid; grid-template-columns: 380px 1fr; min-height: 0; flex: 1; border-bottom: 1px solid var(--theme-control-border); }
.checkpoint-list { overflow: auto; border-right: 1px solid var(--theme-control-border); padding: 10px; }
.checkpoint-item { border: 1px solid var(--theme-control-border); border-radius: 10px; padding: 10px; cursor: pointer; margin-bottom: 8px; background: var(--theme-surface-soft); }
.checkpoint-item.active { border-color: var(--claude-accent); background: var(--theme-tab-active); }
.row { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.row.top { font-size: 12px; color: var(--claude-text-secondary); }
.seq { font-weight: 700; color: var(--claude-text); }
.preview { margin-top: 6px; font-size: 13px; color: var(--claude-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.row.stats { margin-top: 6px; font-size: 12px; }
.plus { color: #16a34a; }
.minus { color: #dc2626; }
.files { color: var(--claude-text-secondary); }
.checkpoint-detail { overflow: auto; padding: 12px 14px; }
.summary { display: flex; gap: 12px; font-size: 13px; margin-bottom: 10px; }
.file-row { display: grid; grid-template-columns: 52px 1fr auto; gap: 10px; align-items: center; border-bottom: 1px dashed var(--theme-control-border); padding: 8px 0; font-size: 13px; cursor: pointer; }
.file-row.expanded { background: color-mix(in srgb, var(--theme-tab-active) 45%, transparent); }
.status { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; color: var(--claude-text-secondary); }
.path { word-break: break-all; color: var(--claude-text); }
.delta { display: inline-flex; gap: 8px; }
.loading, .empty { color: var(--claude-text-secondary); font-size: 13px; padding: 12px 4px; }
.versioning-footer { padding: 12px 18px; display: flex; align-items: center; gap: 10px; justify-content: flex-end; }
.workspace-mismatch-tip { margin-right: auto; color: #dc2626; font-size: 13px; font-weight: 600; }
.versioning-footer select { border: 1px solid var(--theme-control-border); border-radius: 8px; padding: 6px 10px; background: var(--theme-surface-soft); color: var(--claude-text); }
.confirm-btn { border: 0; background: var(--claude-accent); color: #fff; border-radius: 8px; padding: 8px 14px; cursor: pointer; }
.confirm-btn:disabled { opacity: .5; cursor: not-allowed; }

/* 与文件编辑差异展示保持一致 */
.tool-result-diff {
  margin-top: 12px;
  font-family: 'Monaco', 'Menlo', 'Consolas', monospace;
  font-size: 12px;
  line-height: 1.5;
}

.tool-result-diff.scrollable {
  max-height: calc(8 * 1.5em + 16px);
  overflow-y: auto;
  border: 1px solid rgba(0, 0, 0, 0.1);
  border-radius: 6px;
  padding: 8px;
  background: rgba(0, 0, 0, 0.01);
}

.diff-line {
  padding: 2px 4px;
  margin: 1px 0;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.diff-remove {
  background: rgba(255, 0, 0, 0.1);
  color: #c00;
}

.diff-add {
  background: rgba(0, 255, 0, 0.1);
  color: #0a0;
}

.diff-context {
  background: color-mix(in srgb, var(--theme-surface-soft) 70%, transparent);
  color: var(--claude-text-secondary);
}

.approval-note {
  padding: 6px 8px;
  font-size: 11px;
  color: var(--claude-text-secondary);
}

/* 隐藏弹窗内部所有竖向滚动条（保留滚动能力） */
.checkpoint-list,
.checkpoint-detail,
.tool-result-diff.scrollable {
  scrollbar-width: none;
  -ms-overflow-style: none;
}

.checkpoint-list::-webkit-scrollbar,
.checkpoint-detail::-webkit-scrollbar,
.tool-result-diff.scrollable::-webkit-scrollbar {
  width: 0;
  height: 0;
}
</style>
