<script setup>
/**
 * Fancy card-grid view of inbox documents. Hover/focus reveals actions
 * (Review / Reparse / Open invoice / Reject). The parent owns fetching + polling
 * and passes :records; this component is presentational and emits actions.
 */
import { ref, computed, watch, nextTick } from 'vue'

const { t } = useTranslation()
const props = defineProps({
  records: { type: Array, default: () => [] },
  loading: { type: Boolean, default: false },
  selectedId: { type: [Number, String], default: null },
  view: { type: String, default: 'cards' } // 'cards' | 'list'
})
const emit = defineEmits(['review', 'reject', 'reparse', 'open', 'select'])

const listRoot = ref(null)

const money = (n, cur) => (n == null || n === '') ? '—'
  : new Intl.NumberFormat('de-DE', { style: 'currency', currency: cur || 'EUR' }).format(Number(n))

const fmtDate = (s) => {
  if (!s) return ''
  const m = String(s).match(/(\d{4})-(\d{2})-(\d{2})/)
  return m ? `${m[3]}.${m[2]}.${m[1]}` : String(s)
}
// invoice number: strip whitespace / . / , but KEEP '-' (matches index/preview)
const cleanDocNo = (v) => v == null ? '' : String(v).replace(/[\s.,]+/g, '')

// keep the keyboard-selected card/row visible while browsing with ↑/↓
watch(() => props.selectedId, async (id) => {
  if (id == null) return
  await nextTick()
  const el = listRoot.value?.querySelector(`[data-id="${id}"]`)
  if (el) el.scrollIntoView({ block: 'nearest', behavior: 'smooth' })
})

const avgConfidence = (conf) => {
  if (!conf || typeof conf !== 'object') return null
  const vals = Object.values(conf).filter(v => typeof v === 'number')
  if (!vals.length) return null
  return Math.round((vals.reduce((a, b) => a + b, 0) / vals.length) * 100)
}

const tierLabel = (tier) => tier === 0 ? 'E-Invoice XML' : tier === 1 ? 'Text-PDF' : tier === 2 ? 'OCR-Scan' : '—'

const statusMeta = (s) => ({
  processing: { cls: 'is-info', icon: 'ti-loader-2 spin', label: t.value?.processing || 'Wird analysiert…' },
  parsed:     { cls: 'is-success', icon: 'ti-sparkles', label: t.value?.ready_to_review || 'Bereit zur Prüfung' },
  review:     { cls: 'is-success', icon: 'ti-edit', label: t.value?.in_review || 'In Prüfung' },
  linked:     { cls: 'is-link', icon: 'ti-circle-check', label: t.value?.booked || 'Verbucht' },
  rejected:   { cls: 'is-grey', icon: 'ti-x', label: t.value?.rejected || 'Abgelehnt' },
  error:      { cls: 'is-danger', icon: 'ti-alert-triangle', label: t.value?.failed || 'Fehler' }
}[s] || { cls: 'is-grey', icon: 'ti-file', label: s })

const cards = computed(() => props.records.map(r => {
  const ex = r.extracted || {}
  const vendorName = ex?.seller?.name || r.vendorFingerprint?.replace(/^name:/, '') || '—'
  return {
    ...r,
    vendorName,
    initial: (vendorName && vendorName !== '—') ? vendorName.trim().charAt(0).toUpperCase() : '?',
    docNo: cleanDocNo(ex?.documentNo),
    thumb: ex?.__thumb || '',
    date: fmtDate(ex?.issueDate),
    total: ex?.grandTotal,
    currency: ex?.currency || 'EUR',
    conf: avgConfidence(r.confidence),
    meta: statusMeta(r.status)
  }
}))
</script>

<template>
  <div ref="listRoot">
    <div v-if="loading && !cards.length" class="empty">
      <i class="ti ti-loader-2 spin"></i> {{ t.loading || 'Lädt…' }}
    </div>
    <div v-else-if="!cards.length" class="empty">
      <i class="ti ti-inbox empty-ico"></i>
      <div>{{ t.no_incoming_invoices || 'Noch keine Eingangsrechnungen' }}</div>
    </div>

    <!-- LIST VIEW -->
    <div v-else-if="view === 'list'" class="inv-list">
      <div v-for="c in cards" :key="c.id" :data-id="c.id" class="lrow" :class="{ selected: c.id === selectedId }" @click="emit('select', c)">
        <span class="l-thumb-wrap">
          <img v-if="c.thumb" :src="c.thumb" class="l-thumb" alt="" />
          <span v-else class="l-ava">{{ c.initial }}</span>
        </span>
        <span class="l-id">
          <span class="l-vendor" :title="c.vendorName">{{ c.vendorName }}</span>
          <span v-if="c.docNo" class="l-docno">#{{ c.docNo }}</span>
        </span>
        <span class="l-date">{{ c.date || '—' }}</span>
        <span class="l-amount">{{ money(c.total, c.currency) }}</span>
        <span class="l-stat">
          <span class="tag" :class="c.meta.cls"><i class="ti" :class="c.meta.icon"></i> {{ c.meta.label }}</span>
        </span>
        <span class="l-conf">
          <span v-if="c.conf != null" class="conf-pill" :class="c.conf >= 75 ? 'hi' : c.conf >= 50 ? 'mid' : 'lo'">{{ c.conf }}%</span>
        </span>
        <span class="l-actions" @click.stop>
          <button v-if="c.status === 'parsed' || c.status === 'review'" class="button is-small is-primary" @click="emit('review', c)"><i class="ti ti-eye"></i></button>
          <button v-if="c.status === 'linked'" class="button is-small is-link" @click="emit('open', c)"><i class="ti ti-external-link"></i></button>
          <button v-if="c.status === 'error' || c.status === 'parsed' || c.status === 'review'" class="icon-btn" @click="emit('reparse', c)" :title="t.reparse || 'Neu analysieren'"><i class="ti ti-refresh"></i></button>
          <button v-if="c.status !== 'linked' && c.status !== 'rejected'" class="icon-btn danger" @click="emit('reject', c)" :title="t.reject || 'Ablehnen'"><i class="ti ti-trash"></i></button>
        </span>
      </div>
    </div>

    <!-- CARD VIEW -->
    <div v-else class="card-grid">
      <div v-for="c in cards" :key="c.id" :data-id="c.id" class="inv-card" :class="['st-' + c.status, { selected: c.id === selectedId }]" tabindex="0"
           @click="emit('select', c)">
        <span class="accent" :class="'ac-' + c.status"></span>

        <div class="ic-top">
          <span class="tag" :class="c.meta.cls"><i class="ti" :class="c.meta.icon"></i> {{ c.meta.label }}</span>
          <span v-if="c.conf != null" class="conf-pill" :class="c.conf >= 75 ? 'hi' : c.conf >= 50 ? 'mid' : 'lo'">
            {{ c.conf }}%
          </span>
        </div>

        <div class="ic-main">
          <img v-if="c.thumb" :src="c.thumb" class="ic-thumb" alt="" />
          <div v-else class="ic-avatar">{{ c.initial }}</div>
          <div class="ic-idblock">
            <div class="ic-vendor" :title="c.vendorName">{{ c.vendorName }}</div>
            <div v-if="c.docNo" class="ic-docno"><i class="ti ti-hash"></i>{{ c.docNo }}</div>
          </div>
        </div>

        <div class="ic-amount">{{ money(c.total, c.currency) }}</div>

        <div class="ic-meta">
          <span class="ic-chip"><i class="ti ti-file-text"></i>{{ tierLabel(c.sourceTier) }}</span>
          <span v-if="c.date" class="ic-chip"><i class="ti ti-calendar"></i>{{ c.date }}</span>
        </div>

        <div class="ic-file" :title="c.filename"><i class="ti ti-paperclip"></i> {{ c.filename }}</div>
        <div v-if="c.status === 'error' && c.error" class="ic-error" :title="c.error">{{ c.error }}</div>

        <div class="ic-actions" @click.stop>
          <button v-if="c.status === 'parsed' || c.status === 'review'" class="button is-small is-primary" @click="emit('review', c)">
            <i class="ti ti-eye"></i> {{ t.review || 'Prüfen' }}
          </button>
          <button v-if="c.status === 'linked'" class="button is-small is-link" @click="emit('open', c)">
            <i class="ti ti-external-link"></i> {{ t.open_invoice || 'Rechnung öffnen' }}
          </button>
          <span class="spacer"></span>
          <button v-if="c.status === 'error' || c.status === 'parsed' || c.status === 'review'" class="icon-btn" @click="emit('reparse', c)" :title="t.reparse || 'Neu analysieren'">
            <i class="ti ti-refresh"></i>
          </button>
          <button v-if="c.status !== 'linked' && c.status !== 'rejected'" class="icon-btn danger" @click="emit('reject', c)" :title="t.reject || 'Ablehnen'">
            <i class="ti ti-trash"></i>
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped>
.card-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr)); gap: 16px; min-width: 0; }

.inv-card {
  position: relative; border: 1px solid var(--theme-border, #e6e8ec); border-radius: 16px;
  padding: 18px 18px 16px; background: var(--theme-bg-primary, #fff); overflow: hidden; outline: none;
  transition: box-shadow .18s ease, transform .18s ease, border-color .18s ease;
}
.inv-card:hover, .inv-card:focus-within {
  box-shadow: 0 14px 34px rgba(15, 23, 42, .12); transform: translateY(-3px);
  border-color: var(--theme-border-strong, #d4d8de);
}
.inv-card { cursor: pointer; }
.inv-card.selected { border-color: #6366f1; box-shadow: 0 0 0 2px rgba(99,102,241,.35); }
.inv-card.st-processing { opacity: .9; }

/* status accent strip down the left edge */
.accent { position: absolute; left: 0; top: 0; bottom: 0; width: 4px; }
.ac-processing { background: #3b82f6; }
.ac-parsed, .ac-review { background: #22c55e; }
.ac-linked { background: #6366f1; }
.ac-rejected { background: #9ca3af; }
.ac-error { background: #ef4444; }

.ic-top { display: flex; justify-content: space-between; align-items: center; margin-bottom: 14px; }
.tag { font-weight: 600; }
.tag.is-grey { background: #e5e7eb; color: #374151; }
.conf-pill { font-size: .7rem; font-weight: 800; padding: 3px 9px; border-radius: 20px; letter-spacing: .02em; }
.conf-pill.hi { background: #dcfce7; color: #15803d; }
.conf-pill.mid { background: #fef9c3; color: #a16207; }
.conf-pill.lo { background: #fee2e2; color: #b91c1c; }

.ic-main { display: flex; align-items: center; gap: 12px; }
.ic-avatar {
  flex: 0 0 auto; width: 40px; height: 40px; border-radius: 11px; display: flex; align-items: center; justify-content: center;
  font-weight: 800; font-size: 1.05rem; color: #fff;
  background: linear-gradient(135deg, #6366f1, #8b5cf6); box-shadow: 0 4px 10px rgba(99, 102, 241, .25);
}
.ic-thumb { flex: 0 0 auto; width: 42px; height: 56px; object-fit: cover; object-position: top center; border-radius: 7px; border: 1px solid var(--theme-border,#e5e7eb); background: #fff; box-shadow: 0 2px 6px rgba(0,0,0,.08); }
.ic-idblock { min-width: 0; }
.ic-vendor { font-weight: 700; font-size: 1rem; color: var(--theme-text-primary, #111827); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ic-docno { font-size: .76rem; color: var(--theme-text-secondary, #94a3b8); display: flex; align-items: center; gap: 2px; margin-top: 1px; }

.ic-amount { font-size: 1.6rem; font-weight: 800; margin: 12px 0 12px; color: var(--theme-text-primary, #0f172a); letter-spacing: -0.02em; }

.ic-meta { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 10px; }
.ic-chip { font-size: .72rem; background: var(--theme-bg-secondary, #f1f5f9); color: var(--theme-text-secondary, #475569); padding: 3px 9px; border-radius: 7px; display: inline-flex; align-items: center; gap: 5px; }

.ic-file { font-size: .74rem; color: var(--theme-text-secondary, #94a3b8); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 5px; }
.ic-error { font-size: .74rem; color: #b91c1c; margin-top: 8px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.ic-actions { display: flex; align-items: center; gap: 8px; margin-top: 14px; opacity: 0; transform: translateY(4px); transition: opacity .18s ease, transform .18s ease; }
.inv-card:hover .ic-actions, .inv-card:focus-within .ic-actions, .inv-card.st-processing .ic-actions { opacity: 1; transform: none; }
.spacer { flex: 1; }
.icon-btn { width: 32px; height: 32px; border-radius: 9px; border: 1px solid var(--theme-border, #e5e7eb); background: var(--theme-bg-secondary, #f8fafc); color: var(--theme-text-secondary, #475569); cursor: pointer; display: inline-flex; align-items: center; justify-content: center; transition: background .12s ease, color .12s ease; }
.icon-btn:hover { background: #eef2f7; }
.icon-btn.danger:hover { background: #fee2e2; color: #b91c1c; border-color: #fecaca; }

/* list view */
.inv-list { display: flex; flex-direction: column; border: 1px solid var(--theme-border,#e6e8ec); border-radius: 12px; overflow: hidden; background: var(--theme-bg-primary,#fff); }
/* fixed grid → every column keeps its position even when a cell is empty (no row shifting) */
.lrow { display: grid; grid-template-columns: 38px minmax(0, 1fr) 92px 116px 170px 52px 112px; align-items: center; gap: 12px; padding: 9px 14px; border-bottom: 1px solid var(--theme-border,#eef0f3); cursor: pointer; transition: background .12s ease; }
.lrow:last-child { border-bottom: none; }
.lrow:hover { background: var(--theme-bg-secondary,#f8fafc); }
.lrow.selected { background: #eef2ff; box-shadow: inset 3px 0 0 #6366f1; }
.l-thumb-wrap { display: flex; }
.l-thumb { width: 30px; height: 40px; object-fit: cover; object-position: top; border-radius: 4px; border: 1px solid var(--theme-border,#e5e7eb); display: block; }
.l-ava { width: 30px; height: 30px; border-radius: 8px; display: flex; align-items: center; justify-content: center; font-weight: 800; font-size: .8rem; color: #fff; background: linear-gradient(135deg,#6366f1,#8b5cf6); }
.l-id { display: flex; flex-direction: column; min-width: 0; }
.l-vendor { font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; color: var(--theme-text-primary,#1f2937); }
.l-docno { font-size: .74rem; color: var(--theme-text-secondary,#94a3b8); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.l-date { font-size: .8rem; color: var(--theme-text-secondary,#64748b); white-space: nowrap; }
.l-amount { font-weight: 700; text-align: right; color: var(--theme-text-primary,#0f172a); white-space: nowrap; }
.l-stat { min-width: 0; overflow: hidden; }
.l-stat .tag { max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: inline-flex; align-items: center; gap: 4px; }
.l-conf { display: flex; }
.l-actions { display: flex; gap: 5px; justify-content: flex-end; }
@media (max-width: 720px) {
  .lrow { grid-template-columns: 34px minmax(0, 1fr) 96px 92px; }
  .l-date, .l-stat, .l-conf { display: none; }
}

.empty { text-align: center; color: var(--theme-text-secondary, #94a3b8); padding: 56px 0; font-size: .92rem; }
.empty-ico { font-size: 2.4rem; display: block; margin-bottom: 10px; opacity: .6; }
.spin { animation: spin 1s linear infinite; display: inline-block; }
@keyframes spin { to { transform: rotate(360deg); } }
</style>
