<script setup>
// Customer dashboard widget: a month calendar that marks the warehouse's
// non-working business days in red (hover shows the record name), with the
// non-working days of the shown month listed below and an info button that
// explains the shipping-time implications. Reads the tenant-scoped,
// active-only feed from /api/dashboard/non-working-days.
const { t } = useTranslation()

// No top-level await: this widget renders inside a v-if section that flips
// after the dashboard's onMounted, so keeping setup synchronous avoids the
// "async component must be nested in <Suspense>" trap. server:false makes it a
// client-only fetch (the browser sends the auth cookies itself).
const { data, pending } = useFetch('/api/dashboard/non-working-days', {
  headers: useRequestHeaders(['cookie']),
  lazy: true,
  server: false
})

const records = computed(() => data.value?.records || [])

const pad = (n) => String(n).padStart(2, '0')

const now = new Date()
const todayStr = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`

// 0-11 month, navigable back/forward; defaults to the current month.
const viewYear = ref(now.getFullYear())
const viewMonth = ref(now.getMonth())

// German-first, week starts Monday.
const weekdays = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So']

const monthLabel = computed(() =>
  new Date(viewYear.value, viewMonth.value, 1).toLocaleDateString('de-DE', { month: 'long', year: 'numeric' })
)

const isCurrentMonth = computed(() =>
  viewYear.value === now.getFullYear() && viewMonth.value === now.getMonth()
)

// First record whose [DateFrom..DateTo] span covers the given YYYY-MM-DD.
// DateTo is optional → a single-day closure (DateTo defaults to DateFrom).
// Plain string comparison is safe for zero-padded ISO dates.
const findEntry = (dateStr) =>
  records.value.find((r) => {
    const from = r.dateFrom
    const to = r.dateTo || r.dateFrom
    return dateStr >= from && dateStr <= to
  }) || null

const monthCells = computed(() => {
  const year = viewYear.value
  const month = viewMonth.value
  const first = new Date(year, month, 1)
  const lead = (first.getDay() + 6) % 7 // Monday-first leading blanks
  const daysInMonth = new Date(year, month + 1, 0).getDate()
  const cells = []
  for (let i = 0; i < lead; i++) cells.push(null)
  for (let d = 1; d <= daysInMonth; d++) {
    const dateStr = `${year}-${pad(month + 1)}-${pad(d)}`
    const dow = new Date(year, month, d).getDay()
    cells.push({
      day: d,
      date: dateStr,
      weekend: dow === 0 || dow === 6,
      entry: findEntry(dateStr)
    })
  }
  return cells
})

const fmtDay = (s) => {
  if (!s) return ''
  const [y, m, d] = s.split('-')
  return `${d}.${m}.${y}`
}

// Upcoming non-working days of the shown month, formatted for the list below.
// "Upcoming" = the entry has not ended yet (to >= today), so already-passed
// holidays of the current month drop off; in a future month every entry
// qualifies, in a past month none do.
const monthEntries = computed(() => {
  const year = viewYear.value
  const month = viewMonth.value
  const monthStart = `${year}-${pad(month + 1)}-01`
  const monthEnd = `${year}-${pad(month + 1)}-${pad(new Date(year, month + 1, 0).getDate())}`
  return records.value
    .filter((r) => {
      const from = r.dateFrom
      const to = r.dateTo || r.dateFrom
      return from <= monthEnd && to >= monthStart && to >= todayStr
    })
    .slice()
    .sort((a, b) => a.dateFrom.localeCompare(b.dateFrom))
    .map((r) => ({
      id: r.id,
      name: r.name || '—',
      label: (r.dateTo && r.dateTo !== r.dateFrom)
        ? `${fmtDay(r.dateFrom)} – ${fmtDay(r.dateTo)}`
        : fmtDay(r.dateFrom)
    }))
})

const prevMonth = () => {
  if (viewMonth.value === 0) { viewMonth.value = 11; viewYear.value-- }
  else viewMonth.value--
}
const nextMonth = () => {
  if (viewMonth.value === 11) { viewMonth.value = 0; viewYear.value++ }
  else viewMonth.value++
}
const goToday = () => {
  viewYear.value = now.getFullYear()
  viewMonth.value = now.getMonth()
}

const showInfo = ref(false)

// Collapsed by default — the body (calendar grid + month list) is hidden until
// the user clicks the header / prominent chevron to expand it.
const collapsed = ref(true)
const toggleCollapsed = () => { collapsed.value = !collapsed.value }
</script>

<template>
  <article class="fcard fcard--red nwd-card">
    <header class="fcard__head fcard__head--toggle" @click="toggleCollapsed">
      <span class="fcard__icon"><i class="ti ti-calendar-off"></i></span>
      <div class="fcard__titles">
        <h3 class="fcard__title">{{ t.nwd_title || 'Feiertage' }}</h3>
      </div>
      <button
        type="button"
        class="nwd-info-btn"
        :title="t.nwd_info_hint || 'Hinweis zu Lieferzeiten'"
        @click.stop="showInfo = true"
      >
        <i class="ti ti-info-circle"></i>
      </button>
      <i class="ti ti-chevron-down fcard__chevron fcard__chevron--prominent" :class="{ 'fcard__chevron--open': !collapsed }"></i>
    </header>

    <!-- When collapsed AND there are no upcoming Feiertage (and we're done
         loading), the body has nothing to show — keep it hidden so the card is
         just its header + the chevron the user can expand to see the calendar. -->
    <div v-show="!collapsed || pending || monthEntries.length" class="fcard__body">
      <!-- Calendar grid (nav + weekday header + day cells) — only when expanded.
           The Feiertage list below stays visible even when collapsed. -->
      <div v-show="!collapsed" class="nwd-calendar">
        <!-- Month navigation (back / forward / jump to current month) -->
        <div class="nwd-nav">
          <button type="button" class="nwd-nav__btn" :title="t.nwd_prev || 'Vorheriger Monat'" @click="prevMonth">
            <i class="ti ti-chevron-left"></i>
          </button>
          <div class="nwd-nav__label">{{ monthLabel }}</div>
          <button type="button" class="nwd-nav__btn" :title="t.nwd_next || 'Nächster Monat'" @click="nextMonth">
            <i class="ti ti-chevron-right"></i>
          </button>
          <button v-if="!isCurrentMonth" type="button" class="nwd-nav__today" @click="goToday">
            {{ t.nwd_today || 'Heute' }}
          </button>
        </div>

        <!-- Weekday header -->
        <div class="nwd-grid nwd-grid--head">
          <span v-for="w in weekdays" :key="w" class="nwd-wd">{{ w }}</span>
        </div>

        <!-- Day cells -->
        <div class="nwd-grid">
          <template v-for="(cell, i) in monthCells" :key="i">
            <span v-if="!cell" class="nwd-cell nwd-cell--blank"></span>
            <span
              v-else
              class="nwd-cell"
              :class="{
                'nwd-cell--off': cell.entry,
                'nwd-cell--today': cell.date === todayStr,
                'nwd-cell--weekend': cell.weekend && !cell.entry
              }"
              :title="cell.entry ? cell.entry.name : ''"
            >
              {{ cell.day }}
            </span>
          </template>
        </div>
      </div>

      <!-- Upcoming Feiertage of the shown month. Rendered only while loading or
           when there is at least one upcoming entry — when none remain we show
           nothing here (no empty-state text), leaving just the card header. -->
      <div v-if="pending || monthEntries.length" class="nwd-list" :class="{ 'nwd-list--bare': collapsed }">
        <p class="nwd-list__title">{{ t.nwd_list_title || 'Nächste Feiertage im' }} {{ monthLabel }}</p>
        <div v-if="pending" class="nwd-list__empty"><i class="ti ti-loader-2 nwd-spin"></i></div>
        <ul v-else class="nwd-entries">
          <li v-for="e in monthEntries" :key="e.id" class="nwd-entry">
            <span class="nwd-entry__dot"></span>
            <span class="nwd-entry__date">{{ e.label }}</span>
            <span class="nwd-entry__name" :title="e.name">{{ e.name }}</span>
          </li>
        </ul>
      </div>
    </div>

    <!-- Info modal (teleported to body — the .fcard hover transform would
         otherwise become the containing block for a fixed overlay). -->
    <Teleport to="body">
      <div v-if="showInfo" class="nwd-modal" role="dialog" aria-modal="true">
        <div class="nwd-modal__backdrop" @click="showInfo = false"></div>
        <div class="nwd-modal__card">
          <header class="nwd-modal__head">
            <span class="nwd-modal__icon"><i class="ti ti-info-circle"></i></span>
            <h4 class="nwd-modal__title">{{ t.nwd_info_title || 'Hinweis zu Lieferzeiten' }}</h4>
            <button type="button" class="nwd-modal__close" :title="t.close || 'Schließen'" @click="showInfo = false">
              <i class="ti ti-x"></i>
            </button>
          </header>
          <div class="nwd-modal__body">
            <p class="nwd-modal__lead">{{ t.nwd_sub || 'Tage, an denen keine Sendungen bearbeitet oder versendet werden.' }}</p>
            <p>
              {{ t.nwd_info_text || 'Bitte berücksichtigen Sie diese Feiertage und passen Sie Ihre Lieferzeiten auf Marktplätzen und in Ihren Webshops entsprechend an. An diesen Tagen werden keine Sendungen bearbeitet oder versendet.' }}
            </p>
            <ul class="nwd-legend">
              <li><span class="nwd-legend__swatch nwd-legend__swatch--off"></span> {{ t.nwd_legend_holiday || 'Feiertage' }}</li>
              <li><span class="nwd-legend__swatch nwd-legend__swatch--weekend"></span> {{ t.nwd_legend_weekend || 'Wochenenden (Sa & So) – ebenfalls kein Versand' }}</li>
            </ul>
          </div>
          <footer class="nwd-modal__foot">
            <button type="button" class="button is-primary" @click="showInfo = false">
              {{ t.nwd_understood || 'Verstanden' }}
            </button>
          </footer>
        </div>
      </div>
    </Teleport>
  </article>
</template>

<style scoped>
/* ── Self-contained copy of the dashboard .fcard look ─────────────────────
   index.vue's .fcard styles are `scoped`, so they don't reach this child
   component's inner elements — we replicate the pieces we use here. */
.fcard {
  --accent: #dc2626;
  --accent-soft: rgba(220, 38, 38, 0.10);
  display: flex;
  flex-direction: column;
  background: var(--theme-bg-primary, #fff);
  border: 1px solid var(--theme-border, #eef0f3);
  border-top: 3px solid var(--accent);
  border-radius: 12px;
  overflow: hidden;
  transition: box-shadow 0.2s ease, transform 0.2s ease;
}
.fcard:hover { box-shadow: 0 8px 24px rgba(15, 23, 42, 0.08); transform: translateY(-1px); }
.fcard__head {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  padding: 0.875rem 1rem;
  border-bottom: 1px solid var(--theme-border, #eef0f3);
  background: linear-gradient(180deg, var(--accent-soft) 0%, transparent 100%);
}
.fcard__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: var(--accent);
  color: #fff;
  font-size: 1.1rem;
  flex-shrink: 0;
}
.fcard__titles { display: flex; flex-direction: column; min-width: 0; flex: 1; }
.fcard__title {
  margin: 0;
  font-size: 0.95rem;
  font-weight: 700;
  color: var(--theme-text-primary, #0f172a);
  line-height: 1.2;
}
.fcard__sub {
  margin: 0.125rem 0 0;
  font-size: 0.75rem;
  color: var(--theme-text-secondary, #64748b);
  line-height: 1.3;
}
.fcard__body {
  padding: 0.875rem 1rem 1rem;
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  min-height: 0;
}
/* Calendar grid wrapper — preserves the gap between nav / weekday header / day
   cells now that they're nested (the list lives outside it, always visible). */
.nwd-calendar { display: flex; flex-direction: column; gap: 0.5rem; }

/* ── Info button ──────────────────────────────────────────────────────── */
.nwd-info-btn {
  flex-shrink: 0;
  width: 28px;
  height: 28px;
  border-radius: 7px;
  border: 1px solid var(--theme-border, #e2e8f0);
  background: transparent;
  color: var(--theme-text-secondary, #94a3b8);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1rem;
  transition: background 0.15s ease, color 0.15s ease;
}
.nwd-info-btn:hover { background: var(--accent-soft); color: var(--accent); }

/* ── Collapsible header + prominent chevron ───────────────────────────────
   Mirrors the missing-products card in index.vue so both cards collapse the
   same way. The chevron is a filled accent circle so the "open" affordance
   stands out instead of being a faint glyph. */
.fcard__head--toggle { cursor: pointer; user-select: none; }
.fcard__head--toggle:hover { background: linear-gradient(180deg, var(--accent-soft) 0%, transparent 140%); }
.fcard__chevron {
  align-self: center;
  flex-shrink: 0;
  color: var(--theme-text-secondary, #94a3b8);
  font-size: 1.1rem;
  transition: transform 0.2s ease, background 0.15s ease;
}
.fcard__chevron--prominent {
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--accent);
  color: #fff;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-size: 1.2rem;
  box-shadow: 0 2px 6px rgba(220, 38, 38, 0.35);
}
.fcard__chevron--prominent:hover { background: #b91c1c; }
.fcard__chevron--open { transform: rotate(180deg); }

/* ── Month nav ────────────────────────────────────────────────────────── */
.nwd-nav { display: flex; align-items: center; gap: 0.5rem; margin-bottom: 0.25rem; }
.nwd-nav__label {
  flex: 1;
  text-align: center;
  font-weight: 700;
  font-size: 0.9rem;
  text-transform: capitalize;
  color: var(--theme-text-primary, #0f172a);
}
.nwd-nav__btn {
  width: 28px;
  height: 28px;
  border-radius: 7px;
  border: 1px solid var(--theme-border, #e2e8f0);
  background: transparent;
  color: var(--theme-text-secondary, #64748b);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.nwd-nav__btn:hover { background: var(--accent-soft); color: var(--accent); }
.nwd-nav__today {
  font-size: 0.72rem;
  font-weight: 700;
  padding: 0.25rem 0.55rem;
  border-radius: 7px;
  border: 1px solid var(--accent);
  background: var(--accent-soft);
  color: var(--accent);
  cursor: pointer;
  white-space: nowrap;
}

/* ── Month grid ───────────────────────────────────────────────────────── */
.nwd-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.nwd-grid--head { margin-bottom: 2px; }
.nwd-wd {
  text-align: center;
  font-size: 0.68rem;
  font-weight: 700;
  color: var(--theme-text-secondary, #94a3b8);
  padding: 2px 0;
}
.nwd-cell {
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 7px;
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--theme-text-primary, #334155);
  background: var(--theme-bg-secondary, #f8fafc);
}
.nwd-cell--blank { background: transparent; }
/* Weekends (Sa/So) are non-shipping days too — greyed out, distinct from the
   very light regular cells and from the red Feiertage. */
.nwd-cell--weekend { color: var(--theme-text-secondary, #94a3b8); background: rgba(100, 116, 139, 0.18); }
.nwd-cell--today { outline: 2px solid var(--accent); outline-offset: -2px; }
.nwd-cell--off {
  background: #dc2626;
  color: #fff;
  cursor: help;
  box-shadow: 0 1px 3px rgba(220, 38, 38, 0.35);
}
.nwd-cell--off:hover { background: #b91c1c; }

/* ── Month list ───────────────────────────────────────────────────────── */
.nwd-list {
  margin-top: 0.625rem;
  border-top: 1px solid var(--theme-border, #eef0f3);
  padding-top: 0.625rem;
}
/* When collapsed the list sits directly under the header — drop the divider
   that only makes sense when the calendar grid is above it. */
.nwd-list--bare { margin-top: 0; border-top: none; padding-top: 0; }
.nwd-list__title {
  margin: 0 0 0.4rem;
  font-size: 0.74rem;
  font-weight: 700;
  color: var(--theme-text-secondary, #64748b);
  text-transform: capitalize;
}
.nwd-list__empty { font-size: 0.8rem; color: var(--theme-text-secondary, #94a3b8); }
.nwd-entries { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.nwd-entry { display: flex; align-items: center; gap: 0.5rem; font-size: 0.82rem; }
.nwd-entry__dot { width: 9px; height: 9px; border-radius: 50%; background: #dc2626; flex-shrink: 0; }
.nwd-entry__date { font-weight: 700; color: #b91c1c; white-space: nowrap; font-variant-numeric: tabular-nums; }
.nwd-entry__name {
  color: var(--theme-text-primary, #334155);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nwd-spin { display: inline-block; animation: nwd-spin 0.8s linear infinite; }
@keyframes nwd-spin { to { transform: rotate(360deg); } }
</style>

<!-- Non-scoped: the modal is teleported to <body>, so scoped attributes
     wouldn't match it (documented teleport + scoped-CSS gotcha). -->
<style>
.nwd-modal {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 1rem;
}
.nwd-modal__backdrop {
  position: absolute;
  inset: 0;
  background: rgba(15, 23, 42, 0.5);
  backdrop-filter: blur(2px);
}
.nwd-modal__card {
  position: relative;
  width: 100%;
  max-width: 440px;
  background: var(--theme-bg-primary, #fff);
  border-radius: 12px;
  box-shadow: 0 20px 60px rgba(15, 23, 42, 0.3);
  overflow: hidden;
}
.nwd-modal__head {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 1rem 1.125rem;
  border-bottom: 1px solid var(--theme-border, #eef0f3);
}
.nwd-modal__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: rgba(220, 38, 38, 0.10);
  color: #dc2626;
  font-size: 1.2rem;
  flex-shrink: 0;
}
.nwd-modal__title {
  margin: 0;
  flex: 1;
  font-size: 1.02rem;
  font-weight: 700;
  color: var(--theme-text-primary, #0f172a);
}
.nwd-modal__close {
  border: none;
  background: transparent;
  color: var(--theme-text-secondary, #94a3b8);
  cursor: pointer;
  font-size: 1.1rem;
  line-height: 1;
  padding: 4px;
  border-radius: 6px;
}
.nwd-modal__close:hover { background: var(--theme-bg-secondary, #f1f5f9); color: var(--theme-text-primary, #0f172a); }
.nwd-modal__body {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding: 1.125rem;
  color: var(--theme-text-primary, #334155);
  font-size: 0.92rem;
  line-height: 1.55;
}
.nwd-modal__body p { margin: 0; }
.nwd-modal__lead { font-weight: 600; }
.nwd-legend {
  list-style: none;
  margin: 0;
  padding: 0.75rem 0 0;
  border-top: 1px solid var(--theme-border, #eef0f3);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}
.nwd-legend li { display: flex; align-items: center; gap: 0.5rem; font-size: 0.85rem; }
.nwd-legend__swatch { width: 16px; height: 16px; border-radius: 5px; flex-shrink: 0; }
.nwd-legend__swatch--off { background: #dc2626; }
.nwd-legend__swatch--weekend { background: rgba(100, 116, 139, 0.18); border: 1px solid var(--theme-border, #e2e8f0); }
.nwd-modal__foot {
  display: flex;
  justify-content: flex-end;
  padding: 0.875rem 1.125rem;
  border-top: 1px solid var(--theme-border, #eef0f3);
}
</style>
