<template>
  <div class="admin-board-channels">
    <!-- Page Header -->
    <div class="page-header">
      <div class="header-row">
        <div>
          <h1>Board Channels</h1>
          <p>Create Slack channels for cooperative tags. New channels are created in Slack when you click Create Channel.</p>
        </div>
        <div class="header-actions">
          <button class="btn btn-primary" @click="openCreateModal">+ New Channel</button>
        </div>
      </div>
    </div>

    <!-- Unmapped Tags Indicator -->
    <div v-if="unmappedTags.length > 0" class="unmapped-block">
      <div class="section-label">Unmapped Cooperative Tags</div>
      <p class="unmapped-hint">These cooperative tags are not yet mapped to any board channel:</p>
      <div class="tag-pills">
        <span v-for="tag in unmappedTags" :key="tag.slug" class="tag-pill tag-pill-warning">
          {{ tag.label }}
        </span>
      </div>
    </div>

    <!-- Channels List -->
    <div class="channels-list">
      <div v-if="!channels.length" class="empty-state">
        <p>No board channels configured yet.</p>
        <p class="empty-hint">Click "+ New Channel" to create your first board channel in Slack.</p>
      </div>

      <table v-else class="channels-table">
        <thead>
          <tr>
            <th>Channel</th>
            <th>Mapped Tags</th>
            <th class="actions-col">Actions</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="channel in channels" :key="channel._id">
            <td class="name-cell">
              <div class="channel-name">{{ channel.name }}</div>
              <div class="channel-id">{{ channel.slackChannelId }}</div>
            </td>
            <td>
              <div class="tag-pills">
                <span
                  v-for="slug in channel.tagSlugs || []"
                  :key="slug"
                  class="tag-pill"
                >
                  {{ tagLabel(slug) }}
                </span>
                <span v-if="!(channel.tagSlugs || []).length" class="tag-empty">—</span>
              </div>
            </td>
            <td class="actions-cell">
              <button class="link-btn" @click="openEditModal(channel)">Edit</button>
              <button class="link-btn link-btn-danger" @click="deleteChannel(channel)">Delete</button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>

    <!-- Create / Edit Modal -->
    <div v-if="showModal" class="modal-overlay" @click.self="closeModal">
      <div class="modal">
        <div class="modal-header">
          <h2>{{ editingId ? 'Edit Channel' : 'New Channel' }}</h2>
          <button class="modal-close" @click="closeModal">&times;</button>
        </div>
        <div class="modal-body">
          <div class="field">
            <label>Name</label>
            <input v-model="formData.name" type="text" placeholder="e.g., coop-formation" />
            <p v-if="!editingId" class="help-text">A new Slack channel will be created with this name. Lowercase, letters/numbers/dashes only.</p>
          </div>
          <div v-if="editingId" class="field">
            <label>Slack Channel ID</label>
            <input v-model="formData.slackChannelId" type="text" placeholder="C0123456789" />
            <p class="help-text">The Slack channel ID (starts with C).</p>
          </div>
          <div class="field">
            <label>Mapped Tags</label>
            <p class="help-text">Cooperative tags that route posts to this channel.</p>
            <div class="pill-grid">
              <button
                v-for="tag in cooperativeTags"
                :key="tag.slug"
                type="button"
                class="pill"
                :class="{
                  selected: formData.tagSlugs.includes(tag.slug),
                  disabled: tagOwner(tag.slug) && !formData.tagSlugs.includes(tag.slug),
                }"
                :disabled="!!(tagOwner(tag.slug) && !formData.tagSlugs.includes(tag.slug))"
                :title="tagOwner(tag.slug) && !formData.tagSlugs.includes(tag.slug)
                  ? `Already mapped to ${tagOwner(tag.slug)}`
                  : ''"
                @click="toggleTag(tag.slug)"
              >{{ tag.label }}<span
                v-if="tagOwner(tag.slug) && !formData.tagSlugs.includes(tag.slug)"
                class="pill-owner"
              > · {{ tagOwner(tag.slug) }}</span></button>
              <p v-if="!cooperativeTags.length" class="help-text">No cooperative tags available.</p>
            </div>
            <p class="help-text">Each tag can only be mapped to one channel.</p>
          </div>
        </div>
        <div class="modal-actions">
          <button class="btn" @click="closeModal">Cancel</button>
          <button class="btn btn-primary" :disabled="saving" @click="saveChannel">
            {{ saving ? 'Saving...' : (editingId ? 'Save Changes' : 'Create Channel') }}
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
definePageMeta({
  layout: 'admin',
  middleware: 'admin',
})

const toast = useToast()

const { channels, fetchChannels } = useBoardChannels()

const { data: tagsData } = await useFetch('/api/tags')

const cooperativeTags = computed(() =>
  (tagsData.value?.tags || []).filter((t) => t.pool === 'cooperative'),
)

const tagLabelMap = computed(() => {
  const map = {}
  for (const tag of tagsData.value?.tags || []) {
    map[tag.slug] = tag.label
  }
  return map
})

const tagLabel = (slug) => tagLabelMap.value[slug] || slug

const mappedSlugs = computed(() => {
  const set = new Set()
  for (const ch of channels.value) {
    for (const slug of ch.tagSlugs || []) set.add(slug)
  }
  return set
})

// Map of slug -> channel name, EXCLUDING the channel currently being edited.
const otherChannelTagMap = computed(() => {
  const map = {}
  for (const ch of channels.value) {
    if (editingId.value && String(ch._id) === String(editingId.value)) continue
    for (const slug of ch.tagSlugs || []) map[slug] = ch.name
  }
  return map
})

const tagOwner = (slug) => otherChannelTagMap.value[slug] || ''

const unmappedTags = computed(() =>
  cooperativeTags.value.filter((t) => !mappedSlugs.value.has(t.slug)),
)

// ---- Modal State ----
const showModal = ref(false)
const editingId = ref(null)
const saving = ref(false)
const formData = reactive({
  name: '',
  slackChannelId: '',
  tagSlugs: [],
})

const resetForm = () => {
  formData.name = ''
  formData.slackChannelId = ''
  formData.tagSlugs = []
}

const openCreateModal = () => {
  editingId.value = null
  resetForm()
  showModal.value = true
}

const openEditModal = (channel) => {
  editingId.value = channel._id
  formData.name = channel.name || ''
  formData.slackChannelId = channel.slackChannelId || ''
  formData.tagSlugs = [...(channel.tagSlugs || [])]
  showModal.value = true
}

const closeModal = () => {
  showModal.value = false
  editingId.value = null
  resetForm()
}

const toggleTag = (slug) => {
  const idx = formData.tagSlugs.indexOf(slug)
  if (idx === -1) formData.tagSlugs.push(slug)
  else formData.tagSlugs.splice(idx, 1)
}

const saveChannel = async () => {
  if (!formData.name.trim()) {
    toast.add({
      title: 'Missing fields',
      description: 'Name is required.',
      color: 'red',
    })
    return
  }
  if (editingId.value && !formData.slackChannelId.trim()) {
    toast.add({
      title: 'Missing fields',
      description: 'Slack channel ID is required.',
      color: 'red',
    })
    return
  }

  saving.value = true
  try {
    const body = {
      name: formData.name.trim(),
      tagSlugs: formData.tagSlugs,
    }
    if (formData.slackChannelId.trim()) {
      body.slackChannelId = formData.slackChannelId.trim()
    }
    if (editingId.value) {
      await $fetch(`/api/admin/board-channels/${editingId.value}`, {
        method: 'PATCH',
        body,
      })
      toast.add({ title: 'Channel updated', color: 'green' })
    } else {
      await $fetch('/api/admin/board-channels', {
        method: 'POST',
        body,
      })
      toast.add({ title: 'Channel created', color: 'green' })
    }
    await fetchChannels()
    closeModal()
  } catch (err) {
    toast.add({
      title: 'Save failed',
      description: err.data?.statusMessage || err.message,
      color: 'red',
    })
  } finally {
    saving.value = false
  }
}

const deleteChannel = async (channel) => {
  if (!window.confirm(`Delete channel "${channel.name}"? This cannot be undone.`)) return
  try {
    await $fetch(`/api/admin/board-channels/${channel._id}`, { method: 'DELETE' })
    toast.add({ title: 'Channel deleted', color: 'green' })
    await fetchChannels()
  } catch (err) {
    toast.add({
      title: 'Delete failed',
      description: err.data?.statusMessage || err.message,
      color: 'red',
    })
  }
}

onMounted(() => {
  fetchChannels()
})
</script>

<style scoped>
.admin-board-channels {
  padding: 24px;
  max-width: 1100px;
}

.page-header {
  margin-bottom: 24px;
  padding-bottom: 16px;
  border-bottom: 1px dashed var(--border);
}

.header-row {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: 16px;
}

.page-header h1 {
  font-family: 'Brygada 1918', serif;
  font-size: 28px;
  margin-bottom: 4px;
}

.page-header p {
  color: var(--text-dim);
  font-size: 13px;
}

.header-actions {
  display: flex;
  gap: 8px;
}

/* ---- Unmapped Indicator ---- */
.unmapped-block {
  border: 1px dashed var(--border);
  padding: 16px;
  margin-bottom: 24px;
  background: var(--surface);
}

.unmapped-hint {
  font-size: 12px;
  color: var(--text-dim);
  margin: 4px 0 12px;
}

.section-label {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: 8px;
}

/* ---- Tag Pills ---- */
.tag-pills {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}

.tag-pill {
  display: inline-block;
  padding: 2px 9px;
  font-size: 11px;
  font-family: "Commit Mono", monospace;
  background: transparent;
  border: 1px dashed var(--border);
  color: var(--text-dim);
}

.tag-pill-warning {
  border-color: var(--ember);
  color: var(--ember);
}

.tag-empty {
  color: var(--text-faint);
  font-size: 12px;
}

/* ---- Table ---- */
.channels-list {
  border: 1px dashed var(--border);
  background: var(--bg);
}

.channels-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}

.channels-table th,
.channels-table td {
  padding: 10px 14px;
  text-align: left;
  border-bottom: 1px dashed var(--border);
  vertical-align: top;
}

.channels-table thead th {
  font-size: 10px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: normal;
  background: var(--surface);
}

.channels-table tbody tr:last-child td {
  border-bottom: none;
}

.channel-name {
  font-weight: 600;
}
.channel-id {
  font-family: 'Commit Mono', monospace;
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 2px;
}

.actions-col {
  width: 160px;
}

.actions-cell {
  white-space: nowrap;
}

.link-btn {
  background: none;
  border: none;
  color: var(--candle-dim);
  font-size: 12px;
  cursor: pointer;
  padding: 2px 6px;
  text-decoration: underline;
}

.link-btn:hover {
  color: var(--candle);
}

.link-btn-danger {
  color: var(--ember);
}

.link-btn-danger:hover {
  color: var(--ember);
}

.empty-state {
  padding: 40px 20px;
  text-align: center;
  color: var(--text-dim);
}

.empty-hint {
  font-size: 12px;
  color: var(--text-faint);
  margin-top: 4px;
}

/* ---- Modal ---- */
.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 100;
  padding: 20px;
}

.modal {
  background: var(--bg);
  border: 1px dashed var(--border);
  width: 100%;
  max-width: 520px;
  max-height: 90vh;
  display: flex;
  flex-direction: column;
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px dashed var(--border);
}

.modal-header h2 {
  font-family: 'Brygada 1918', serif;
  font-size: 20px;
  margin: 0;
}

.modal-close {
  background: none;
  border: none;
  font-size: 24px;
  cursor: pointer;
  color: var(--text-dim);
  line-height: 1;
}

.modal-body {
  padding: 20px;
  overflow-y: auto;
}

.modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  padding: 16px 20px;
  border-top: 1px dashed var(--border);
}

.field {
  margin-bottom: 16px;
}

.field label {
  display: block;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--text-dim);
  margin-bottom: 6px;
}

.field input {
  width: 100%;
  padding: 8px 10px;
  background: var(--input-bg);
  border: 1px solid var(--border);
  font-family: inherit;
  font-size: 13px;
  color: var(--text);
}

.field input:focus {
  outline: none;
  border-color: var(--candle);
}

.help-text {
  font-size: 11px;
  color: var(--text-faint);
  margin-top: 4px;
}

.pill-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  max-height: 240px;
  overflow-y: auto;
}
.pill {
  display: inline-flex;
  align-items: center;
  padding: 2px 9px;
  border: 1px dashed var(--border);
  background: transparent;
  color: var(--text-faint);
  font-size: 11px;
  font-family: "Commit Mono", monospace;
  cursor: pointer;
  user-select: none;
  transition: all 0.12s;
  white-space: nowrap;
}
.pill:hover {
  color: var(--text-dim);
  border-color: var(--border-d);
}
.pill.selected {
  background: var(--surface);
  color: var(--text-bright);
  border-color: var(--candle);
  border-style: solid;
}
.pill.disabled,
.pill:disabled {
  opacity: 0.45;
  cursor: not-allowed;
}
.pill.disabled:hover {
  color: var(--text-faint);
  border-color: var(--border);
}
.pill-owner {
  font-size: 10px;
  color: var(--text-faint);
  margin-left: 2px;
}
</style>
