<template>
  <div
    class="fc-dl-row"
    :class="[`fc-dl-row--${event.status || 'unknown'}`]"
    @click="$emit('open', event.id)"
  >
    <!-- Colored left edge marks the run's status; matches the row's
         status-chip color but reads at a glance without needing to
         parse the chip text. -->
    <div class="fc-dl-row__bar" />

    <v-chip
      :color="statusColor"
      size="small"
      variant="tonal"
      :prepend-icon="statusIcon"
      class="fc-dl-row__status"
    >{{ statusLabel }}</v-chip>

    <RouterLink
      v-if="event.artist_slug"
      :to="`/artist/${event.artist_slug}`"
      class="fc-dl-row__artist"
      @click.stop
    >{{ event.artist_name }}</RouterLink>
    <span v-else class="fc-dl-row__artist fc-dl-row__artist--missing">—</span>

    <PlatformChip
      v-if="event.platform"
      :platform="event.platform"
      size="x-small"
      class="fc-dl-row__platform"
    />
    <span v-else class="fc-dl-row__platform-missing">—</span>

    <span class="fc-dl-row__time" :title="event.started_at">
      {{ fmtTime(event.started_at) }}
    </span>

    <v-chip
      v-if="event.files_count > 0"
      size="x-small" variant="tonal" color="info"
      prepend-icon="mdi-image-multiple"
      class="fc-dl-row__files"
    >{{ event.files_count }}</v-chip>
    <span v-else class="fc-dl-row__no-files" aria-label="no new files">·</span>

    <span class="fc-dl-row__duration">
      {{ fmtDuration(event.summary?.duration_seconds) }}
    </span>

    <v-chip
      v-if="event.error"
      color="error" size="x-small" variant="tonal"
      prepend-icon="mdi-alert-octagon"
      class="fc-dl-row__error"
      :title="event.error"
    >{{ truncateError(event.error) }}</v-chip>
    <span v-else class="fc-dl-row__error-spacer" />

    <div class="fc-dl-row__actions" @click.stop>
      <v-btn
        v-if="event.status === 'error' && event.source_id"
        icon size="x-small" variant="text" color="warning"
        :loading="retrying"
        @click.stop="onRetry"
      >
        <v-icon size="small">mdi-refresh</v-icon>
        <v-tooltip activator="parent" location="top">Retry source check</v-tooltip>
      </v-btn>
      <v-btn icon size="x-small" variant="text" @click.stop="$emit('open', event.id)">
        <v-icon size="small">mdi-information-outline</v-icon>
        <v-tooltip activator="parent" location="top">Details</v-tooltip>
      </v-btn>
      <v-btn
        v-if="event.artist_slug"
        icon size="x-small" variant="text"
        :to="`/artist/${event.artist_slug}`"
        @click.stop
      >
        <v-icon size="small">mdi-account-circle</v-icon>
        <v-tooltip activator="parent" location="top">Open artist</v-tooltip>
      </v-btn>
    </div>
  </div>
</template>

<script setup>
import { toast } from '../../utils/toast.js'
import { computed, ref } from 'vue'
import { RouterLink } from 'vue-router'

import PlatformChip from '../subscriptions/PlatformChip.vue'
import { useSourcesStore } from '../../stores/sources.js'
import { downloadStatusColor, downloadStatusIcon, downloadStatusLabel } from '../../utils/downloadStatus.js'
import { formatDateTime } from '../../utils/date.js'

const props = defineProps({ event: { type: Object, required: true } })
defineEmits(['open'])

const sourcesStore = useSourcesStore()
const retrying = ref(false)

const statusColor = computed(() => downloadStatusColor(props.event.status))
const statusIcon = computed(() => downloadStatusIcon(props.event.status))
const statusLabel = computed(() => downloadStatusLabel(props.event.status))

function fmtTime(iso) {
  return iso ? formatDateTime(iso) : '—'
}
function fmtDuration(sec) {
  if (sec == null) return '—'
  if (sec < 60) return `${sec.toFixed(1)}s`
  const m = Math.floor(sec / 60), s = Math.floor(sec % 60)
  return `${m}m ${s}s`
}
function truncateError(msg) {
  const s = String(msg || '')
  if (s.length <= 60) return s
  return s.slice(0, 57) + '…'
}

async function onRetry() {
  if (!props.event.source_id) return
  retrying.value = true
  try {
    const body = await sourcesStore.checkNow(props.event.source_id)
    // Audit 2026-06-02: the previous handler unconditionally toasted
    // "re-queued" even when the platform was in cooldown (202 +
    // status='deferred'). Operator thought work was in flight when
    // nothing was actually enqueued.
    if (body?.status === 'deferred') {
      toast({ text: 'Retry deferred — platform in cooldown', type: 'info' })
    } else {
      toast({ text: 'Source check re-queued', type: 'success' })
    }
  } catch (e) {
    const isInFlight = !!e?.body?.download_event_id
    toast({
      text: isInFlight ? 'Already running' : `Retry failed: ${e?.detail || e?.message || e}`,
      type: isInFlight ? 'info' : 'error',
    })
  } finally {
    retrying.value = false
  }
}
</script>

<style scoped>
.fc-dl-row {
  position: relative;
  display: grid;
  grid-template-columns:
    /* bar */    4px
    /* status */ 120px
    /* artist */ minmax(120px, 1.2fr)
    /* plat   */ 140px
    /* time   */ 140px
    /* files  */ 60px
    /* dur    */ 70px
    /* error  */ minmax(0, 1.5fr)
    /* actions*/ 120px;
  gap: 0.6rem;
  align-items: center;
  padding: 0.55rem 0.75rem 0.55rem 0;
  border-bottom: 1px solid rgb(var(--v-theme-on-surface-variant) / 0.15);
  cursor: pointer;
  transition: background 0.12s ease;
}
.fc-dl-row:hover {
  background: rgb(var(--v-theme-on-surface) / 0.04);
}
.fc-dl-row__bar {
  width: 4px;
  align-self: stretch;
  border-radius: 0 2px 2px 0;
}
.fc-dl-row--ok      .fc-dl-row__bar { background: rgb(var(--v-theme-success)); }
.fc-dl-row--error   .fc-dl-row__bar { background: rgb(var(--v-theme-error));   }
.fc-dl-row--running .fc-dl-row__bar { background: rgb(var(--v-theme-info));    }
.fc-dl-row--skipped .fc-dl-row__bar { background: rgb(var(--v-theme-warning)); }
.fc-dl-row--pending .fc-dl-row__bar { background: rgb(var(--v-theme-on-surface-variant) / 0.4); }

.fc-dl-row__status { justify-self: start; }
.fc-dl-row__artist {
  color: rgb(var(--v-theme-on-surface));
  text-decoration: none;
  font-weight: 500;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fc-dl-row__artist--missing,
.fc-dl-row__platform-missing,
.fc-dl-row__no-files {
  color: rgb(var(--v-theme-on-surface-variant));
  opacity: 0.5;
}
.fc-dl-row__artist:hover { color: rgb(var(--v-theme-accent)); }
.fc-dl-row__platform { justify-self: start; }
.fc-dl-row__time,
.fc-dl-row__duration {
  color: rgb(var(--v-theme-on-surface-variant));
  font-size: 0.85rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.fc-dl-row__no-files {
  text-align: center;
  font-size: 1.1rem;
}
.fc-dl-row__error {
  justify-self: start;
  max-width: 100%;
}
.fc-dl-row__error :deep(.v-chip__content) {
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.fc-dl-row__error-spacer { /* keeps the grid column reserved */ }

.fc-dl-row__actions {
  display: flex; gap: 2px;
  justify-self: end;
  opacity: 0.5;
  transition: opacity 0.12s ease;
}
.fc-dl-row:hover .fc-dl-row__actions { opacity: 1; }
</style>
