<script setup lang="ts">
import { ref, computed } from "vue";
import { renderMarkdown } from "@/utils/markdown";
import type { DiffLine } from "@/composables/useAssist";

const props = defineProps<{
  phase: "streaming" | "review";
  label: string;
  streamingText: string;
  diff: DiffLine[];
  proposedText: string;
}>();

const emit = defineEmits<{
  accept: [];
  reject: [];
  cancel: [];
}>();

const showFullText = ref(false);

const renderedStreaming = computed(() => renderMarkdown(props.streamingText));
const renderedProposed = computed(() => renderMarkdown(props.proposedText));

const markers: Record<DiffLine["type"], string> = {
  equal: " ",
  delete: "−",
  insert: "+",
};
</script>

<template>
  <!-- ── Streaming ───────────────────────────────────────────────── -->
  <div v-if="phase === 'streaming'" class="iap iap-streaming">
    <div class="iap-header">
      <span class="iap-pulse"></span>
      <span class="iap-label">{{ label }}</span>
      <button class="iap-btn-cancel" @click="emit('cancel')">Cancel</button>
    </div>
    <div class="iap-stream-preview prose" v-html="renderedStreaming"></div>
    <div v-if="!streamingText" class="iap-waiting">Waiting for model…</div>
  </div>

  <!-- ── Review ─────────────────────────────────────────────────── -->
  <div v-else-if="phase === 'review'" class="iap iap-review">
    <div class="iap-header">
      <span class="iap-review-title">Proposed changes</span>
      <button class="iap-btn-toggle" @click="showFullText = !showFullText">
        {{ showFullText ? "Show diff" : "Show full text" }}
      </button>
      <div class="iap-actions">
        <button class="iap-btn-accept" @click="emit('accept')">✓ Accept</button>
        <button class="iap-btn-reject" @click="emit('reject')">✗ Reject</button>
      </div>
    </div>

    <!-- Diff view -->
    <div v-if="!showFullText" class="iap-diff">
      <div
        v-for="(line, i) in diff"
        :key="i"
        :class="['iap-diff-line', `iap-diff-${line.type}`]"
      >
        <span class="iap-diff-marker">{{ markers[line.type] }}</span>
        <span class="iap-diff-text">{{ line.text }}</span>
      </div>
      <div v-if="!diff.length" class="iap-diff-empty">No changes.</div>
    </div>

    <!-- Full text view -->
    <div v-else class="iap-full-text prose" v-html="renderedProposed"></div>
  </div>
</template>

<style scoped>
.iap {
  border-radius: var(--fs-radius-sm);
  margin-bottom: 0.75rem;
  overflow: hidden;
  border: 1px solid var(--fs-border-color);
  background: var(--fs-surface-page);
}

/* ── Header ── */
.iap-header {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.75rem;
  font-size: 0.85rem;
  border-bottom: 1px solid var(--fs-border-color);
  background: var(--fs-surface-raised);
}

/* ── Streaming ── */
.iap-streaming {
  border-color: var(--fs-accent);
}
.iap-streaming .iap-header {
  background: color-mix(in srgb, var(--fs-accent) 8%, var(--fs-surface-raised));
}

.iap-pulse {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--fs-accent);
  flex-shrink: 0;
  animation: iap-pulse 1.2s ease-in-out infinite;
}
@keyframes iap-pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%       { opacity: 0.4; transform: scale(0.8); }
}

.iap-label {
  flex: 1;
  font-weight: 500;
  color: var(--fs-text-primary);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

.iap-btn-cancel {
  background: none;
  border: 1px solid var(--fs-border-color);
  color: var(--fs-text-secondary);
  border-radius: var(--fs-radius-sm);
  padding: 0.15rem 0.5rem;
  cursor: pointer;
  font-size: 0.8rem;
  font-family: inherit;
  flex-shrink: 0;
}
.iap-btn-cancel:hover {
  border-color: var(--fs-error);
  color: var(--fs-error);
}

.iap-stream-preview {
  padding: 0.75rem;
  font-size: 0.9rem;
  min-height: 2.5rem;
  max-height: 320px;
  overflow-y: auto;
}

.iap-waiting {
  padding: 0.75rem;
  font-size: 0.85rem;
  color: var(--fs-text-tertiary);
}

/* ── Review ── */
.iap-review-title {
  flex: 1;
  font-weight: 600;
  color: var(--fs-text-primary);
}

.iap-btn-toggle {
  background: none;
  border: 1px solid var(--fs-border-color);
  color: var(--fs-text-secondary);
  border-radius: var(--fs-radius-sm);
  padding: 0.15rem 0.5rem;
  cursor: pointer;
  font-size: 0.78rem;
  font-family: inherit;
}
.iap-btn-toggle:hover {
  border-color: var(--fs-accent);
  color: var(--fs-accent);
}

.iap-actions {
  display: flex;
  gap: 0.35rem;
}

.iap-btn-accept,
.iap-btn-reject {
  border: none;
  border-radius: var(--fs-radius-sm);
  padding: 0.2rem 0.65rem;
  cursor: pointer;
  font-size: 0.8rem;
  font-family: inherit;
  font-weight: var(--fs-weight-medium);
}
.iap-btn-accept {
  background: var(--fs-success);
  color: var(--fs-text-on-action);
}
.iap-btn-accept:hover { opacity: 0.85; }

.iap-btn-reject {
  background: var(--fs-surface-raised);
  color: var(--fs-text-secondary);
  border: 1px solid var(--fs-border-color);
}
.iap-btn-reject:hover {
  border-color: var(--fs-error);
  color: var(--fs-error);
}

/* ── Diff ── */
.iap-diff {
  font-family: ui-monospace, "Cascadia Code", "Fira Mono", monospace;
  font-size: 0.82rem;
  line-height: 1.6;
  max-height: 440px;
  overflow-y: auto;
  padding: 0.4rem 0;
}

.iap-diff-line {
  display: flex;
  gap: 0.5rem;
  padding: 0 0.75rem;
  white-space: pre-wrap;
  word-break: break-word;
}

.iap-diff-equal  { color: var(--fs-text-tertiary); }
.iap-diff-delete {
  background: color-mix(in srgb, var(--fs-error) 10%, transparent);
  color: var(--fs-error);
}
.iap-diff-insert {
  background: color-mix(in srgb, var(--fs-success) 10%, transparent);
  color: var(--fs-success);
}

.iap-diff-marker {
  width: 1ch;
  flex-shrink: 0;
  font-weight: 700;
  user-select: none;
}

.iap-diff-empty {
  padding: 0.75rem;
  color: var(--fs-text-tertiary);
  font-size: 0.85rem;
  font-family: inherit;
}

/* ── Full text ── */
.iap-full-text {
  padding: 0.75rem;
  font-size: 0.9rem;
  max-height: 440px;
  overflow-y: auto;
}
</style>
