<template>
  <div>
    <div class="page-header">
      <h1>Notification Types</h1>
      <div class="actions">
        <router-link to="/settings" class="btn btn-secondary">Back to Settings</router-link>
        <button class="btn btn-primary" @click="openNew">New Type</button>
      </div>
    </div>

    <div class="card">
      <div class="table-container">
        <table>
          <thead>
            <tr>
              <th>Name</th>
              <th>Color</th>
              <th>Display style</th>
              <th>Employee</th>
              <th>Auto-expiry</th>
              <th>Active</th>
              <th></th>
            </tr>
          </thead>
          <tbody>
            <tr v-for="t in types" :key="t.notificationtypeid">
              <td>
                <strong>{{ t.typename }}</strong>
                <div v-if="t.typedescription" class="muted">{{ t.typedescription }}</div>
              </td>
              <td>
                <span class="swatch" :style="{ backgroundColor: swatchColor(t.typecolor) }"></span>
                <span class="mono">{{ t.typecolor }}</span>
              </td>
              <td>
                <span class="badge">#{{ t.boardorder ?? 100 }}</span>
                <span class="badge">{{ t.displaystyle || 'standard' }}</span>
                <span v-if="t.boardcategory" class="badge badge-secondary">{{ t.boardcategory }}</span>
              </td>
              <td>
                <span v-if="t.splitperemployee" class="badge badge-success">split</span>
                <span v-if="t.showemployeephoto" class="badge badge-success">photo</span>
                <span v-if="!t.splitperemployee && !t.showemployeephoto" class="muted">-</span>
              </td>
              <td>{{ expiryLabel(t) }}</td>
              <td>
                <span class="badge" :class="t.isactive ? 'badge-success' : 'badge-secondary'">
                  {{ t.isactive ? 'yes' : 'no' }}
                </span>
              </td>
              <td class="actions">
                <button class="btn btn-sm btn-secondary" @click="openEdit(t)">Edit</button>
              </td>
            </tr>
            <tr v-if="!loading && !types.length">
              <td colspan="7" class="muted" style="text-align:center;">No notification types.</td>
            </tr>
          </tbody>
        </table>
      </div>
    </div>

    <!-- Editor -->
    <div v-if="editing" class="modal-overlay">
      <div class="modal-panel">
        <h2>{{ form.notificationtypeid ? 'Edit' : 'New' }} Notification Type</h2>

        <div class="form-grid">
          <label class="field">
            <span>Name</span>
            <input v-model="form.typename" type="text" maxlength="50" placeholder="e.g. Safety Alert" />
          </label>

          <label class="field">
            <span>Description</span>
            <input v-model="form.typedescription" type="text" placeholder="Shown to editors" />
          </label>

          <label class="field">
            <span>Color</span>
            <ColorSwatchPicker v-model="form.typecolor" />
          </label>

          <label class="field">
            <span>Display style</span>
            <select v-model="form.displaystyle">
              <option value="standard">Standard rows</option>
              <option value="carousel">Carousel (rotating photo card)</option>
              <option value="grid">Grid (cycling row of tiles)</option>
              <option value="banner">Banner (full-width strip)</option>
            </select>
          </label>

          <label class="field">
            <span>Board order</span>
            <input v-model.number="form.boardorder" type="number" min="0" max="999" step="10" />
            <small class="muted">
              Where this type's row sits on the shopfloor board, lowest first
              (Recognition 10, Recertification 20, everything else 100). Leave
              gaps so a new row can be slotted in without renumbering. Types
              sharing a category take the lowest order among them.
            </small>
          </label>

          <label class="field">
            <span>Board category (optional)</span>
            <input v-model="form.boardcategory" type="text" maxlength="50"
                   placeholder="its own row" />
            <small class="muted">
              Types sharing a category share one row on the shopfloor board,
              under the category name. Blank gives this type a row of its own.
              Only types with the same display style can share a row.
            </small>
          </label>

          <label class="field">
            <span>Keep showing after end (minutes)</span>
            <input v-model.number="form.gracewindowminutes" type="number"
                   min="0" max="1440" step="5" />
            <small class="muted">
              0 means a card leaves the shopfloor board the moment its end time
              passes. A higher number keeps it up that long afterwards, marked
              RESOLVED - useful for an incident worth acknowledging once it
              clears.
            </small>
          </label>

          <label class="field checkbox">
            <input v-model="form.splitperemployee" type="checkbox" />
            <span>Split one card per employee</span>
          </label>

          <label class="field checkbox">
            <input v-model="form.showemployeephoto" type="checkbox" />
            <span>Show employee photo + name (HR lookup)</span>
          </label>

          <label class="field">
            <span>Auto-expiry</span>
            <select v-model="form.expirymode">
              <option value="none">None (stays until end time / indefinite)</option>
              <option value="duration">Duration (N days after posting)</option>
              <option value="dailytime">Daily reset (clears at an hour, Eastern)</option>
            </select>
          </label>

          <label v-if="form.expirymode === 'duration'" class="field">
            <span>Days</span>
            <input v-model.number="form.expirydays" type="number" min="1" />
          </label>

          <label v-if="form.expirymode === 'dailytime'" class="field">
            <span>Hour (0-23, Eastern)</span>
            <input v-model.number="form.expiryhour" type="number" min="0" max="23" />
          </label>

          <label class="field checkbox">
            <input v-model="form.isactive" type="checkbox" />
            <span>Active</span>
          </label>
        </div>

        <p v-if="error" class="error">{{ error }}</p>

        <div class="modal-actions">
          <button class="btn btn-secondary" @click="close">Cancel</button>
          <button class="btn btn-primary" :disabled="saving || !form.typename" @click="save">
            {{ saving ? 'Saving...' : 'Save' }}
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { notificationsApi } from '@/api'
import ColorSwatchPicker from '@/components/ColorSwatchPicker.vue'
import { apiError } from '@/utils/apiError'

const types = ref([])
const loading = ref(true)
const editing = ref(false)
const saving = ref(false)
const error = ref('')
const form = ref({})

// Keyword typecolors the shopfloor board maps to fixed accent colors; anything
// else is a literal hex.
const KEYWORD_COLORS = {
  recognition: '#ffc107',
  recertification: '#0d6efd',
  training: '#17a2b8',
  success: '#04b962',
  warning: '#ff8800',
  danger: '#f5365c',
  info: '#14abef',
  primary: '#7934f3'
}

function isHex(c) {
  return typeof c === 'string' && /^#[0-9a-fA-F]{3,8}$/.test(c)
}
function swatchColor(c) {
  if (!c) return '#888'
  return KEYWORD_COLORS[c] || c
}

function expiryLabel(t) {
  const grace = t.gracewindowminutes ?? 0
  // The tail only means something next to the rule that ends the card.
  const tail = grace > 0 ? ` (+${grace}m resolved)` : ''
  if (t.expirymode === 'duration' && t.expirydays) return `${t.expirydays} day(s)${tail}`
  if (t.expirymode === 'dailytime') return `daily @ ${String(t.expiryhour ?? 8).padStart(2, '0')}:00 ET${tail}`
  return grace > 0 ? `none${tail}` : 'none'
}

async function load() {
  loading.value = true
  try {
    const response = await notificationsApi.types.list()
    types.value = response.data.data || []
  } catch (err) {
    console.error('Error loading notification types:', err)
  } finally {
    loading.value = false
  }
}

function openNew() {
  error.value = ''
  form.value = {
    typename: '',
    typedescription: '',
    typecolor: '#17a2b8',
    displaystyle: 'standard',
    splitperemployee: false,
    showemployeephoto: false,
    expirymode: 'none',
    expirydays: null,
    expiryhour: null,
    gracewindowminutes: 0,
    boardcategory: '',
    boardorder: 100,
    isactive: true
  }
  editing.value = true
}

function openEdit(t) {
  error.value = ''
  form.value = {
    notificationtypeid: t.notificationtypeid,
    typename: t.typename || '',
    typedescription: t.typedescription || '',
    typecolor: t.typecolor || '#17a2b8',
    displaystyle: t.displaystyle || 'standard',
    splitperemployee: !!t.splitperemployee,
    showemployeephoto: !!t.showemployeephoto,
    expirymode: t.expirymode || 'none',
    expirydays: t.expirydays ?? null,
    expiryhour: t.expiryhour ?? null,
    gracewindowminutes: t.gracewindowminutes ?? 0,
    boardcategory: t.boardcategory || '',
    boardorder: t.boardorder ?? 100,
    isactive: t.isactive !== false
  }
  editing.value = true
}

function close() {
  editing.value = false
}

async function save() {
  saving.value = true
  error.value = ''
  const payload = { ...form.value }
  try {
    if (payload.notificationtypeid) {
      await notificationsApi.types.update(payload.notificationtypeid, payload)
    } else {
      await notificationsApi.types.create(payload)
    }
    editing.value = false
    await load()
  } catch (err) {
    error.value = apiError(err, 'Save failed.')
  } finally {
    saving.value = false
  }
}

onMounted(load)
</script>

<style scoped>
.muted {
  color: var(--text-light);
  font-size: 0.85rem;
}
.mono {
  font-family: monospace;
  font-size: 0.85rem;
}
.swatch {
  display: inline-block;
  width: 16px;
  height: 16px;
  border-radius: 3px;
  vertical-align: middle;
  margin-right: 6px;
  border: 1px solid var(--border);
}
.swatch.lg {
  width: 28px;
  height: 28px;
}

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 40px 16px;
  overflow-y: auto;
  z-index: 1000;
}
.modal-panel {
  /* Solid, not var(--bg-card): the card variable is translucent in dark mode
     (rgba(0,0,61,0.4)) so cards glass over the page, which left this dialog
     see-through with the table legible behind it. */
  background: var(--bg-card-solid);
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 24px;
  width: 100%;
  max-width: 560px;
  box-shadow: 0 12px 40px rgba(0, 0, 0, 0.4);
}
.modal-panel h2 {
  margin: 0 0 18px;
}

.form-grid {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.field > span {
  font-size: 0.85rem;
  color: var(--text-light);
}
.field input[type="text"],
.field input[type="number"],
.field select {
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
  color: var(--text);
}
.field.checkbox {
  flex-direction: row;
  align-items: center;
  gap: 8px;
}
.field.checkbox > span {
  color: var(--text);
  font-size: 1rem;
}
.color-row {
  display: flex;
  align-items: center;
  gap: 10px;
}
.color-row input[type="text"] {
  flex: 1;
}

.error {
  color: var(--danger);
  margin: 12px 0 0;
}
.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 22px;
}
</style>
