<template>
  <div class="flex h-screen overflow-hidden bg-slate-100 text-slate-900 dark:bg-slate-950 dark:text-slate-100">

    <!-- Bootstrap / first-run state -->
    <div v-if="isBootstrap" class="flex flex-col items-center justify-center w-full h-full text-center px-6">
      <div class="max-w-md">
        <div class="text-5xl mb-4">🎫</div>
        <h2 class="text-2xl font-bold text-slate-800 dark:text-slate-100 mb-2">Ticketing isn’t set up yet</h2>
        <p class="text-slate-500 dark:text-slate-400 mb-6">Create your first group in Settings to get started. Default priorities will be seeded automatically.</p>
        <Link :href="route('ticketing.settings')" class="inline-block bg-indigo-600 text-white px-5 py-2.5 rounded-xl text-sm font-medium hover:bg-indigo-700 transition">Go to Settings</Link>
      </div>
    </div>

    <template v-else>
    <aside class="hidden w-72 shrink-0 border-r border-slate-200 bg-white/90 backdrop-blur dark:border-slate-800 dark:bg-slate-900/90 lg:flex lg:flex-col">
      <div class="border-b border-slate-200 p-5 dark:border-slate-800">
        <div class="flex items-center justify-between gap-3">
          <div>
            <p class="text-xs font-semibold uppercase tracking-[0.22em] text-slate-400">Shared inbox</p>
            <h1 class="mt-1 text-2xl font-semibold tracking-tight">Ticketing</h1>
          </div>
          <Link
            :href="route('ticketing.create')"
            class="inline-flex h-10 items-center justify-center rounded-xl bg-slate-900 px-4 text-sm font-medium text-white transition hover:bg-slate-700 dark:bg-indigo-500 dark:hover:bg-indigo-400"
          >
            New
          </Link>
        </div>
      </div>

      <div class="flex-1 space-y-6 overflow-y-auto p-5">
        <section class="space-y-2">
          <label class="text-xs font-semibold uppercase tracking-[0.18em] text-slate-400">Group switcher</label>
          <select
            v-model="activeGroupId"
            class="w-full rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm shadow-sm outline-none transition focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100 dark:border-slate-700 dark:bg-slate-800 dark:focus:border-indigo-500 dark:focus:ring-indigo-500/20"
            @change="applyFilters({ group_id: normalizeNullable(activeGroupId) })"
          >
            <option :value="null">All groups</option>
            <option v-for="group in groups" :key="group.id" :value="group.id">{{ group.name }}</option>
          </select>
        </section>

        <section class="space-y-2">
          <div class="flex items-center justify-between">
            <h2 class="text-xs font-semibold uppercase tracking-[0.18em] text-slate-400">Views</h2>
            <span class="text-xs text-slate-400">{{ filteredTickets.length }}</span>
          </div>

          <button
            v-for="view in visibleViews"
            :key="view.key"
            type="button"
            class="flex w-full items-center justify-between rounded-2xl px-3 py-3 text-sm transition"
            :class="currentFilter === view.key
              ? 'bg-slate-900 text-white shadow-sm dark:bg-indigo-500'
              : 'text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800'"
            @click="applyFilters({ filter: view.key === 'all' ? 'all' : view.key })"
          >
            <span>{{ view.label }}</span>
            <span
              class="rounded-full px-2 py-0.5 text-xs"
              :class="currentFilter === view.key ? 'bg-white/15 text-white' : 'bg-slate-200 text-slate-600 dark:bg-slate-800 dark:text-slate-300'"
            >
              {{ viewCount(view.key) }}
            </span>
          </button>
        </section>

        <section class="space-y-3">
          <div class="flex items-center justify-between">
            <h2 class="text-xs font-semibold uppercase tracking-[0.18em] text-slate-400">Priority</h2>
            <button
              v-if="filters.priority_id"
              type="button"
              class="text-xs text-slate-400 transition hover:text-slate-600 dark:hover:text-slate-200"
              @click="applyFilters({ priority_id: undefined })"
            >
              Clear
            </button>
          </div>

          <div class="flex flex-wrap gap-2">
            <button
              v-for="priority in priorities"
              :key="priority.id"
              type="button"
              class="inline-flex items-center gap-2 rounded-full border px-3 py-1.5 text-xs font-medium transition"
              :class="Number(filters.priority_id) === priority.id ? 'shadow-sm' : 'border-slate-200 text-slate-600 hover:bg-slate-100 dark:border-slate-700 dark:text-slate-300 dark:hover:bg-slate-800'"
              :style="priorityChipStyle(priority, Number(filters.priority_id) === priority.id)"
              @click="togglePriority(priority.id)"
            >
              <span class="h-2.5 w-2.5 rounded-full" :style="{ backgroundColor: priority.color || '#94a3b8' }"></span>
              {{ priority.name }}
            </button>
          </div>
        </section>

        <section class="space-y-3">
          <div class="flex items-center justify-between">
            <h2 class="text-xs font-semibold uppercase tracking-[0.18em] text-slate-400">Projects</h2>
            <button
              v-if="filters.project_id"
              type="button"
              class="text-xs text-slate-400 transition hover:text-slate-600 dark:hover:text-slate-200"
              @click="applyFilters({ project_id: undefined })"
            >
              Clear
            </button>
          </div>

          <div class="space-y-1">
            <button
              type="button"
              class="flex w-full items-center justify-between rounded-2xl px-3 py-2.5 text-sm transition"
              :class="!filters.project_id ? 'bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-slate-100' : 'text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800'"
              @click="applyFilters({ project_id: undefined })"
            >
              <span>All projects</span>
              <span class="text-xs text-slate-400">{{ totalProjectCount }}</span>
            </button>

            <button
              v-for="project in projects"
              :key="project.id"
              type="button"
              class="flex w-full items-center justify-between rounded-2xl px-3 py-2.5 text-sm transition"
              :class="Number(filters.project_id) === project.id ? 'bg-slate-100 text-slate-900 dark:bg-slate-800 dark:text-slate-100' : 'text-slate-600 hover:bg-slate-100 dark:text-slate-300 dark:hover:bg-slate-800'"
              @click="applyFilters({ project_id: Number(filters.project_id) === project.id ? undefined : project.id })"
            >
              <span class="truncate">{{ project.name }}</span>
              <span class="rounded-full bg-slate-200 px-2 py-0.5 text-xs text-slate-600 dark:bg-slate-700 dark:text-slate-300">{{ project.ticket_count ?? 0 }}</span>
            </button>
          </div>
        </section>
      </div>
    </aside>

    <main class="flex min-w-0 flex-1 border-r border-slate-200 bg-white dark:border-slate-800 dark:bg-slate-925 xl:max-w-[34rem]">
      <div class="flex min-w-0 flex-1 flex-col">
        <div class="border-b border-slate-200 p-5 dark:border-slate-800">
          <div class="flex items-center justify-between gap-3">
            <div>
              <p class="text-xs font-semibold uppercase tracking-[0.18em] text-slate-400">Queue</p>
              <h2 class="mt-1 text-xl font-semibold tracking-tight">{{ currentViewTitle }}</h2>
            </div>
            <div class="rounded-full border border-slate-200 px-3 py-1 text-xs text-slate-500 dark:border-slate-700 dark:text-slate-300">
              {{ tickets.total }} total
            </div>
          </div>

          <div class="mt-4 flex flex-col gap-3 sm:flex-row">
            <div class="relative flex-1">
              <input
                v-model="search"
                type="text"
                placeholder="Search tickets, people, or numbers"
                class="w-full rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm outline-none transition focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100 dark:border-slate-700 dark:bg-slate-800 dark:focus:border-indigo-500 dark:focus:ring-indigo-500/20"
              />
            </div>
            <select
              v-model="sortBy"
              class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm outline-none transition focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100 dark:border-slate-700 dark:bg-slate-800 dark:focus:border-indigo-500 dark:focus:ring-indigo-500/20"
            >
              <option value="newest">Newest first</option>
              <option value="oldest">Oldest first</option>
              <option value="priority">Priority</option>
              <option value="status">Status</option>
            </select>
          </div>
        </div>

        <div class="min-h-0 flex-1 overflow-y-auto">
          <div v-if="filteredTickets.length === 0" class="flex h-full flex-col items-center justify-center px-6 text-center">
            <div class="rounded-3xl border border-dashed border-slate-300 px-8 py-10 dark:border-slate-700">
              <p class="text-sm font-medium text-slate-500 dark:text-slate-300">Nothing matches the current filters.</p>
              <p class="mt-2 text-sm text-slate-400">Try a different view, search, or priority chip.</p>
            </div>
          </div>

          <button
            v-for="ticket in filteredTickets"
            :key="ticket.id"
            type="button"
            class="flex w-full gap-4 border-b border-slate-100 px-5 py-4 text-left transition hover:bg-slate-50 dark:border-slate-800 dark:hover:bg-slate-900/60"
            :class="selectedTicketId === ticket.id ? 'bg-indigo-50/80 dark:bg-indigo-500/10' : ''"
            @click="selectTicket(ticket.id)"
          >
            <div class="w-1 self-stretch rounded-full" :style="{ backgroundColor: ticket.priority?.color || ticket.group?.color || '#cbd5e1' }"></div>

            <div class="min-w-0 flex-1">
              <div class="flex items-center gap-2">
                <span class="text-xs font-semibold uppercase tracking-[0.12em] text-slate-400">{{ ticket.number }}</span>
                <span :class="badgeClass(ticket.status)" class="inline-flex rounded-full px-2 py-0.5 text-[11px] font-semibold">{{ statusLabel(ticket.status) }}</span>
                <span v-if="hasUnread(ticket)" class="h-2.5 w-2.5 rounded-full bg-sky-500"></span>
              </div>

              <p class="mt-2 truncate text-sm font-semibold text-slate-900 dark:text-slate-100">{{ ticket.title }}</p>

              <div class="mt-3 flex items-center gap-3 text-xs text-slate-500 dark:text-slate-400">
                <div class="flex items-center gap-2">
                  <span class="avatar-ring bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-100">{{ initials(ticket.submitter?.name || ticket.submitter?.email || '?') }}</span>
                  <span class="truncate">{{ ticket.submitter?.name || ticket.submitter?.email || 'Unknown' }}</span>
                </div>
                <span>•</span>
                <span>{{ ageLabel(ticket.created_at) }}</span>
              </div>
            </div>

            <div class="flex shrink-0 flex-col items-end justify-between gap-3">
              <div class="text-xs font-medium text-slate-500 dark:text-slate-400">{{ ticket.priority?.name || 'No priority' }}</div>
              <div class="flex items-center gap-2">
                <span class="text-[11px] uppercase tracking-[0.16em] text-slate-400">Assignee</span>
                <span
                  class="avatar-ring"
                  :class="ticket.assignee ? 'bg-indigo-100 text-indigo-700 dark:bg-indigo-500/20 dark:text-indigo-200' : 'bg-slate-200 text-slate-500 dark:bg-slate-700 dark:text-slate-300'"
                >
                  {{ ticket.assignee ? initials(ticket.assignee.name || ticket.assignee.email) : '—' }}
                </span>
              </div>
            </div>
          </button>
        </div>

        <div v-if="tickets.last_page > 1" class="flex items-center justify-between border-t border-slate-200 px-5 py-3 text-sm dark:border-slate-800">
          <span class="text-slate-500 dark:text-slate-400">Page {{ tickets.current_page }} of {{ tickets.last_page }}</span>
          <div class="flex items-center gap-2">
            <Link
              v-if="tickets.prev_page_url"
              :href="tickets.prev_page_url"
              class="rounded-xl border border-slate-200 px-3 py-1.5 text-slate-600 transition hover:bg-slate-100 dark:border-slate-700 dark:text-slate-300 dark:hover:bg-slate-800"
            >Prev</Link>
            <Link
              v-if="tickets.next_page_url"
              :href="tickets.next_page_url"
              class="rounded-xl border border-slate-200 px-3 py-1.5 text-slate-600 transition hover:bg-slate-100 dark:border-slate-700 dark:text-slate-300 dark:hover:bg-slate-800"
            >Next</Link>
          </div>
        </div>
      </div>
    </main>

    <section class="flex min-w-0 flex-1 flex-col bg-slate-50 dark:bg-slate-950/80">
      <div v-if="!ticketDetail" class="flex h-full items-center justify-center p-8">
        <div class="max-w-md rounded-3xl border border-dashed border-slate-300 bg-white p-10 text-center shadow-sm dark:border-slate-700 dark:bg-slate-900">
          <p class="text-xs font-semibold uppercase tracking-[0.2em] text-slate-400">Conversation</p>
          <h3 class="mt-3 text-2xl font-semibold tracking-tight">Pick a ticket</h3>
          <p class="mt-3 text-sm leading-6 text-slate-500 dark:text-slate-400">
            The right panel becomes the full thread view: metadata, internal notes, and reply composer included. Miracles do happen.
          </p>
        </div>
      </div>

      <template v-else>
        <div class="border-b border-slate-200 bg-white px-6 py-5 dark:border-slate-800 dark:bg-slate-900">
          <div class="flex flex-wrap items-start justify-between gap-4">
            <div class="min-w-0 flex-1">
              <div class="flex flex-wrap items-center gap-2">
                <span class="inline-flex rounded-full px-2.5 py-1 text-xs font-semibold text-white" :style="{ backgroundColor: ticketDetail.group?.color || '#6366f1' }">{{ ticketDetail.number }}</span>
                <span :class="badgeClass(ticketDetail.status)" class="inline-flex rounded-full px-2.5 py-1 text-xs font-semibold">{{ statusLabel(ticketDetail.status) }}</span>
                <span v-if="ticketDetail.priority" class="inline-flex items-center gap-2 rounded-full border border-slate-200 px-2.5 py-1 text-xs font-medium text-slate-600 dark:border-slate-700 dark:text-slate-300">
                  <span class="h-2.5 w-2.5 rounded-full" :style="{ backgroundColor: ticketDetail.priority.color || '#94a3b8' }"></span>
                  {{ ticketDetail.priority.name }}
                </span>
              </div>

              <div class="mt-3 flex items-start gap-3">
                <h3 class="min-w-0 flex-1 text-2xl font-semibold tracking-tight text-slate-900 dark:text-slate-100">{{ ticketDetail.title }}</h3>
                <Link :href="route('ticketing.show', { ticket: ticketDetail.id })" class="text-sm font-medium text-indigo-600 transition hover:text-indigo-500 dark:text-indigo-300">Open full page</Link>
              </div>
            </div>
          </div>

          <div class="mt-5 grid gap-3 md:grid-cols-5">
            <div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 dark:border-slate-800 dark:bg-slate-950/60">
              <div class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400">Assignee</div>
              <div class="mt-2 flex items-center gap-2 text-sm font-medium">
                <span class="avatar-ring bg-indigo-100 text-indigo-700 dark:bg-indigo-500/20 dark:text-indigo-200">{{ ticketDetail.assignee ? initials(ticketDetail.assignee.name || ticketDetail.assignee.email) : '—' }}</span>
                <span class="truncate">{{ ticketDetail.assignee?.name || ticketDetail.assignee?.email || 'Unassigned' }}</span>
              </div>
            </div>

            <div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 dark:border-slate-800 dark:bg-slate-950/60">
              <div class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400">Due date</div>
              <div class="mt-2 text-sm font-medium">{{ formatDate(ticketDetail.due_date, 'No due date') }}</div>
            </div>

            <div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 dark:border-slate-800 dark:bg-slate-950/60">
              <div class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400">Project</div>
              <div class="mt-2 truncate text-sm font-medium">{{ ticketDetail.project?.name || 'No project' }}</div>
            </div>

            <div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 dark:border-slate-800 dark:bg-slate-950/60">
              <div class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400">Submitter</div>
              <div class="mt-2 truncate text-sm font-medium">{{ ticketDetail.submitter?.name || ticketDetail.submitter?.email || 'Unknown' }}</div>
            </div>

            <div class="rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 dark:border-slate-800 dark:bg-slate-950/60">
              <div class="text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400">Opened</div>
              <div class="mt-2 text-sm font-medium">{{ ageLabel(ticketDetail.created_at) }}</div>
            </div>
          </div>

          <div class="mt-4 flex flex-wrap items-center gap-3 text-sm text-slate-500 dark:text-slate-400">
            <span>Group: <strong class="text-slate-700 dark:text-slate-200">{{ ticketDetail.group?.name || 'Unknown' }}</strong></span>
            <span>•</span>
            <span>{{ ticketDetail.messages?.length || 0 }} messages</span>
            <span>•</span>
            <span>{{ ticketDetail.attachments?.length || 0 }} attachments</span>
          </div>

          <div v-if="isAgent" class="mt-5 grid gap-3 lg:grid-cols-4">
            <select v-model="metaForm.status" class="meta-select" @change="saveMeta">
              <option v-for="status in statuses" :key="status.value" :value="status.value">{{ status.label }}</option>
            </select>

            <select v-model="metaForm.priority_id" class="meta-select" @change="saveMeta">
              <option :value="null">No priority</option>
              <option v-for="priority in priorities" :key="priority.id" :value="priority.id">{{ priority.name }}</option>
            </select>

            <select v-model="metaForm.assigned_to" class="meta-select" @change="saveMeta">
              <option :value="null">Unassigned</option>
              <option v-for="agent in detailAgents" :key="agent.id" :value="agent.id">{{ agent.name || agent.email }}</option>
            </select>

            <input v-model="metaForm.due_date" type="date" class="meta-select" @change="saveMeta" />
          </div>
        </div>

        <div class="min-h-0 flex-1 overflow-y-auto px-6 py-6">
          <div v-if="ticketDetail.description" class="mb-6 rounded-3xl border border-slate-200 bg-white p-5 shadow-sm dark:border-slate-800 dark:bg-slate-900">
            <div class="mb-2 text-[11px] font-semibold uppercase tracking-[0.16em] text-slate-400">Description</div>
            <p class="whitespace-pre-wrap text-sm leading-6 text-slate-700 dark:text-slate-300">{{ ticketDetail.description }}</p>
          </div>

          <div v-if="!ticketDetail.messages?.length" class="rounded-3xl border border-dashed border-slate-300 bg-white p-8 text-center text-sm text-slate-500 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-400">
            No messages yet.
          </div>

          <div v-else class="space-y-4">
            <div
              v-for="message in ticketDetail.messages"
              :key="message.id"
              class="flex"
              :class="messageAlignment(message)"
            >
              <div class="max-w-3xl rounded-3xl px-5 py-4 shadow-sm" :class="messageCardClass(message)">
                <div class="flex flex-wrap items-center gap-2 text-xs font-medium opacity-80">
                  <span class="inline-flex items-center gap-2">
                    <span class="avatar-ring bg-white/70 text-slate-700 dark:bg-slate-900/60 dark:text-slate-100">{{ initials(messageAuthor(message)) }}</span>
                    {{ messageRoleLabel(message) }}
                  </span>
                  <span>•</span>
                  <span>{{ message.author?.name || message.author_email || 'Unknown' }}</span>
                  <span>•</span>
                  <span>{{ preciseDate(message.created_at) }}</span>
                </div>

                <p class="mt-3 whitespace-pre-wrap text-sm leading-6">{{ message.body }}</p>

                <div v-if="message.attachments?.length" class="mt-4 flex flex-wrap gap-2">
                  <a
                    v-for="attachment in message.attachments"
                    :key="attachment.id"
                    :href="route('ticketing.attachments.show', { attachment: attachment.id })"
                    class="inline-flex items-center gap-2 rounded-full border border-current/20 px-3 py-1.5 text-xs font-medium transition hover:bg-white/30 dark:hover:bg-slate-900/30"
                    target="_blank"
                  >
                    📎 {{ attachment.filename }}
                  </a>
                </div>
              </div>
            </div>
          </div>
        </div>

        <div class="border-t border-slate-200 bg-white px-6 py-5 dark:border-slate-800 dark:bg-slate-900">
          <div v-if="isAgent" class="mb-4 inline-flex rounded-2xl bg-slate-100 p-1 dark:bg-slate-800">
            <button
              type="button"
              class="rounded-2xl px-4 py-2 text-sm font-medium transition"
              :class="replyMode === 'reply' ? 'bg-white text-slate-900 shadow-sm dark:bg-slate-700 dark:text-white' : 'text-slate-500 dark:text-slate-300'"
              @click="replyMode = 'reply'"
            >Reply</button>
            <button
              type="button"
              class="rounded-2xl px-4 py-2 text-sm font-medium transition"
              :class="replyMode === 'internal' ? 'bg-amber-500 text-white shadow-sm' : 'text-slate-500 dark:text-slate-300'"
              @click="replyMode = 'internal'"
            >Internal note</button>
          </div>

          <form @submit.prevent="sendMessage" class="space-y-3">
            <textarea
              v-model="messageForm.body"
              rows="4"
              required
              class="w-full rounded-3xl border px-4 py-3 text-sm outline-none transition focus:ring-2"
              :class="replyMode === 'internal'
                ? 'border-amber-300 bg-amber-50 text-amber-950 focus:border-amber-400 focus:ring-amber-100 dark:border-amber-700 dark:bg-amber-950/30 dark:text-amber-100 dark:focus:ring-amber-500/20'
                : 'border-slate-200 bg-slate-50 text-slate-900 focus:border-indigo-400 focus:ring-indigo-100 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100 dark:focus:border-indigo-500 dark:focus:ring-indigo-500/20'"
              :placeholder="replyMode === 'internal' ? 'Internal note for agents only…' : 'Reply to the thread…'"
            ></textarea>

            <div class="flex items-center justify-between gap-3">
              <div class="text-xs text-slate-400">
                {{ replyMode === 'internal' ? 'Only agents can see internal notes.' : 'Replies are visible in the ticket thread.' }}
              </div>
              <button
                type="submit"
                :disabled="messageForm.processing"
                class="inline-flex items-center rounded-2xl px-4 py-2 text-sm font-medium text-white transition disabled:cursor-not-allowed disabled:opacity-60"
                :class="replyMode === 'internal' ? 'bg-amber-500 hover:bg-amber-600' : 'bg-slate-900 hover:bg-slate-700 dark:bg-indigo-500 dark:hover:bg-indigo-400'"
              >
                {{ messageForm.processing ? 'Sending…' : replyMode === 'internal' ? 'Save note' : 'Send reply' }}
              </button>
            </div>
          </form>
        </div>
      </template>
    </section>
  </template>
  </div>
</template>

<script setup>
import { computed, ref, watch } from 'vue'
import { Link, router, useForm } from '@inertiajs/vue3'

const props = defineProps({
  tickets: Object,
  groups: Array,
  priorities: Array,
  projects: Array,
  isAgent: Boolean,
  filters: Object,
  ticketDetail: Object,
  detailAgents: Array,
  viewCounts: Object,
  isBootstrap: Boolean,
})

const search = ref('')
const sortBy = ref('newest')
const activeGroupId = ref(props.filters?.group_id ? Number(props.filters.group_id) : null)
const replyMode = ref('reply')

const visibleViews = computed(() => {
  const base = [
    { key: 'all', label: 'All Open' },
    { key: 'mine', label: 'Mine' },
    { key: 'unassigned', label: 'Unassigned' },
    { key: 'pending', label: 'Pending' },
    { key: 'resolved', label: 'Resolved' },
  ]

  return props.isAgent ? base : base.filter((view) => ['all', 'pending', 'resolved'].includes(view.key))
})

const currentFilter = computed(() => props.filters?.filter || 'all')
const selectedTicketId = computed(() => props.ticketDetail?.id ?? (props.filters?.detail ? Number(props.filters.detail) : null))
const currentViewTitle = computed(() => visibleViews.value.find((view) => view.key === currentFilter.value)?.label || 'Tickets')
const totalProjectCount = computed(() => props.projects.reduce((sum, project) => sum + Number(project.ticket_count || 0), 0))

const filteredTickets = computed(() => {
  const term = search.value.trim().toLowerCase()
  const priorityWeight = Object.fromEntries(
    [...props.priorities].sort((a, b) => (a.sort_order ?? 0) - (b.sort_order ?? 0)).map((priority, index, arr) => [priority.id, arr.length - index])
  )

  let items = [...(props.tickets?.data || [])]

  if (term) {
    items = items.filter((ticket) => {
      const haystack = [
        ticket.number,
        ticket.title,
        ticket.status,
        ticket.submitter?.name,
        ticket.submitter?.email,
        ticket.assignee?.name,
        ticket.assignee?.email,
        ticket.priority?.name,
      ].filter(Boolean).join(' ').toLowerCase()

      return haystack.includes(term)
    })
  }

  items.sort((a, b) => {
    if (sortBy.value === 'oldest') {
      return new Date(a.created_at) - new Date(b.created_at)
    }

    if (sortBy.value === 'priority') {
      return (priorityWeight[b.priority_id] || 0) - (priorityWeight[a.priority_id] || 0) || new Date(b.created_at) - new Date(a.created_at)
    }

    if (sortBy.value === 'status') {
      return statusSortValue(a.status) - statusSortValue(b.status) || new Date(b.created_at) - new Date(a.created_at)
    }

    return new Date(b.created_at) - new Date(a.created_at)
  })

  return items
})

const metaForm = useForm({
  status: props.ticketDetail?.status ?? 'open',
  priority_id: props.ticketDetail?.priority_id ?? null,
  assigned_to: props.ticketDetail?.assigned_to ?? null,
  due_date: props.ticketDetail?.due_date ?? null,
})

const messageForm = useForm({
  body: '',
  is_internal: false,
})

watch(
  () => props.ticketDetail,
  (detail) => {
    replyMode.value = 'reply'
    metaForm.defaults({
      status: detail?.status ?? 'open',
      priority_id: detail?.priority_id ?? null,
      assigned_to: detail?.assigned_to ?? null,
      due_date: detail?.due_date ?? null,
    })
    metaForm.reset()
  },
  { immediate: true }
)

const statuses = [
  { value: 'open', label: 'Open' },
  { value: 'in_progress', label: 'In Progress' },
  { value: 'pending', label: 'Pending' },
  { value: 'resolved', label: 'Resolved' },
  { value: 'closed', label: 'Closed' },
]

function normalizeNullable(value) {
  return value === '' || value === null || value === undefined ? undefined : Number(value)
}

function buildParams(overrides = {}) {
  const params = {
    ...props.filters,
    ...overrides,
  }

  Object.keys(params).forEach((key) => {
    if (params[key] === undefined || params[key] === null || params[key] === '') {
      delete params[key]
    }
  })

  return params
}

function applyFilters(overrides = {}) {
  const params = buildParams({ ...overrides, detail: overrides.detail === undefined ? props.filters?.detail : overrides.detail })

  router.get(route('ticketing.index'), params, {
    preserveState: true,
    preserveScroll: true,
    replace: true,
  })
}

function togglePriority(priorityId) {
  applyFilters({ priority_id: Number(props.filters.priority_id) === priorityId ? undefined : priorityId })
}

function selectTicket(ticketId) {
  router.get(route('ticketing.index'), buildParams({ detail: ticketId }), {
    preserveState: true,
    preserveScroll: true,
    replace: true,
    only: ['ticketDetail', 'detailAgents', 'filters'],
  })
}

function saveMeta() {
  if (!props.ticketDetail) return

  metaForm.transform((data) => ({
    ...data,
    priority_id: normalizeNullable(data.priority_id),
    assigned_to: normalizeNullable(data.assigned_to),
    due_date: data.due_date || null,
  })).put(route('ticketing.update', { ticket: props.ticketDetail.id }), {
    preserveScroll: true,
    onSuccess: () => {
      router.reload({ only: ['tickets', 'ticketDetail', 'detailAgents'] })
    },
  })
}

function sendMessage() {
  if (!props.ticketDetail) return

  messageForm.transform((data) => ({
    ...data,
    is_internal: props.isAgent && replyMode.value === 'internal',
  })).post(route('ticketing.messages.store', { ticket: props.ticketDetail.id }), {
    preserveScroll: true,
    onSuccess: () => {
      messageForm.reset()
      router.reload({ only: ['tickets', 'ticketDetail', 'detailAgents'] })
    },
  })
}

function viewCount(key) {
  return props.viewCounts?.[key] ?? 0
}

function initials(value) {
  return String(value || '?')
    .split(/\s+/)
    .filter(Boolean)
    .slice(0, 2)
    .map((part) => part[0])
    .join('')
    .toUpperCase()
}

function badgeClass(status) {
  return {
    open: 'bg-sky-100 text-sky-700 dark:bg-sky-500/20 dark:text-sky-200',
    in_progress: 'bg-violet-100 text-violet-700 dark:bg-violet-500/20 dark:text-violet-200',
    pending: 'bg-amber-100 text-amber-700 dark:bg-amber-500/20 dark:text-amber-200',
    resolved: 'bg-emerald-100 text-emerald-700 dark:bg-emerald-500/20 dark:text-emerald-200',
    closed: 'bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-200',
  }[status] || 'bg-slate-200 text-slate-700 dark:bg-slate-700 dark:text-slate-200'
}

function priorityChipStyle(priority, active) {
  const color = priority.color || '#94a3b8'
  return active
    ? { borderColor: color, backgroundColor: `${color}18`, color }
    : {}
}

function statusLabel(status) {
  return {
    open: 'Open',
    in_progress: 'In Progress',
    pending: 'Pending',
    resolved: 'Resolved',
    closed: 'Closed',
  }[status] || status
}

function statusSortValue(status) {
  return {
    open: 1,
    in_progress: 2,
    pending: 3,
    resolved: 4,
    closed: 5,
  }[status] || 99
}

function ageLabel(value) {
  return relativeTime(value)
}

function preciseDate(value) {
  if (!value) return 'Unknown time'
  return new Date(value).toLocaleString()
}

function formatDate(value, fallback = '—') {
  if (!value) return fallback
  return new Date(value).toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' })
}

function relativeTime(value) {
  if (!value) return '—'
  const date = new Date(value)
  const diff = Math.max(1, Math.floor((Date.now() - date.getTime()) / 1000))
  if (diff < 60) return `${diff}s ago`
  if (diff < 3600) return `${Math.floor(diff / 60)}m ago`
  if (diff < 86400) return `${Math.floor(diff / 3600)}h ago`
  if (diff < 604800) return `${Math.floor(diff / 86400)}d ago`
  return `${Math.floor(diff / 604800)}w ago`
}

function hasUnread(ticket) {
  if (!ticket || !props.ticketDetail) return false
  return ticket.id !== props.ticketDetail.id && ['open', 'pending'].includes(ticket.status)
}

function messageAlignment(message) {
  if (message.is_internal) return 'justify-center'
  return isSubmitterMessage(message) ? 'justify-start' : 'justify-end'
}

function messageCardClass(message) {
  if (message.is_internal) {
    return 'border border-amber-200 bg-amber-50 text-amber-950 dark:border-amber-800 dark:bg-amber-950/40 dark:text-amber-100'
  }

  if (isSubmitterMessage(message)) {
    return 'border border-slate-200 bg-white text-slate-800 dark:border-slate-700 dark:bg-slate-900 dark:text-slate-100'
  }

  return 'bg-slate-900 text-white dark:bg-indigo-500'
}

function isSubmitterMessage(message) {
  return Number(message.user_id) === Number(props.ticketDetail?.submitter_id)
}

function messageRoleLabel(message) {
  if (message.is_internal) return 'Internal note'
  return isSubmitterMessage(message) ? 'Submitter' : 'Agent reply'
}

function messageAuthor(message) {
  return message.author?.name || message.author?.email || message.author_email || 'Unknown'
}
</script>

<style scoped>
.avatar-ring {
  @apply inline-flex h-8 w-8 items-center justify-center rounded-full text-[11px] font-semibold;
}

.meta-select {
  @apply w-full rounded-2xl border border-slate-200 bg-slate-50 px-4 py-3 text-sm outline-none transition focus:border-indigo-400 focus:ring-2 focus:ring-indigo-100 dark:border-slate-700 dark:bg-slate-800 dark:text-slate-100 dark:focus:border-indigo-500 dark:focus:ring-indigo-500/20;
}
</style>
