<script setup lang="ts">
import { useAssignablePersons, useAssignPersonToShift } from '@/composables/api/useShiftAssignments'
import type { AssignablePerson } from '@/types/shiftAssignment'
import type { Shift } from '@/types/section'

const props = defineProps<{
  eventId: string
  sectionId: string
  shift: Shift | null
}>()

const emit = defineEmits<{
  assigned: []
}>()

const modelValue = defineModel<boolean>({ required: true })

const eventIdRef = computed(() => props.eventId)
const shiftIdRef = computed(() => props.shift?.id ?? '')

const { data: assignablePersons, isLoading } = useAssignablePersons(eventIdRef, shiftIdRef)
const { mutateAsync: assignPerson, isPending: isAssigning } = useAssignPersonToShift(eventIdRef)

// Search and filters
const searchQuery = ref('')
const showOnlyAvailable = ref(true)
const selectedCrowdType = ref<string | null>(null)
const assignError = ref<string | null>(null)
const showSuccess = ref(false)
const successName = ref('')

// Clear error on filter changes
watch([searchQuery, showOnlyAvailable, selectedCrowdType], () => {
  assignError.value = null
})

// Reset state when dialog opens
watch(modelValue, (open) => {
  if (open) {
    searchQuery.value = ''
    showOnlyAvailable.value = true
    selectedCrowdType.value = null
    assignError.value = null
  }
})

// Crowd type filter options (derived from data)
const crowdTypeOptions = computed(() => {
  if (!assignablePersons.value) return []
  const seen = new Map<string, string>()
  for (const p of assignablePersons.value) {
    if (p.crowd_type && !seen.has(p.crowd_type.system_type)) {
      seen.set(p.crowd_type.system_type, p.crowd_type.name)
    }
  }

  return Array.from(seen, ([value, title]) => ({ title, value }))
})

// Filtered persons
const filteredPersons = computed(() => {
  if (!assignablePersons.value) return []

  return assignablePersons.value.filter((person) => {
    if (searchQuery.value) {
      const q = searchQuery.value.toLowerCase()
      if (!person.name.toLowerCase().includes(q) && !person.email.toLowerCase().includes(q)) {
        return false
      }
    }

    if (showOnlyAvailable.value) {
      if (!person.is_available || person.already_assigned) return false
    }

    if (selectedCrowdType.value) {
      if (person.crowd_type?.system_type !== selectedCrowdType.value) return false
    }

    return true
  })
})

// Empty state reason
const emptyReason = computed(() => {
  if (!assignablePersons.value?.length) {
    return 'Er zijn geen goedgekeurde personen voor dit evenement.'
  }
  if (showOnlyAvailable.value && !filteredPersons.value.length && assignablePersons.value.length) {
    return 'Alle personen zijn al ingepland voor dit tijdslot. Zet \'Alleen beschikbaar\' uit om alle personen te zien.'
  }

  return 'Geen personen gevonden voor deze zoekopdracht.'
})

function getInitials(name: string) {
  return name
    .split(' ')
    .map(p => p[0])
    .join('')
    .toUpperCase()
    .slice(0, 2)
}

async function handleAssign(person: AssignablePerson) {
  if (!props.shift) return
  assignError.value = null

  try {
    await assignPerson({
      sectionId: props.sectionId,
      shiftId: props.shift.id,
      personId: person.id,
    })
    emit('assigned')
    successName.value = person.name
    showSuccess.value = true
  }
  catch (error: any) {
    const message = error.response?.data?.errors?.person_id?.[0]
      ?? error.response?.data?.message
      ?? 'Er is een fout opgetreden bij het toewijzen.'
    assignError.value = message
  }
}
</script>

<template>
  <VDialog
    v-model="modelValue"
    max-width="600"
    :fullscreen="$vuetify.display.smAndDown"
  >
    <VCard>
      <VCardTitle class="d-flex align-center justify-space-between">
        <span>Persoon toewijzen</span>
        <VBtn
          icon="tabler-x"
          variant="text"
          size="small"
          @click="modelValue = false"
        />
      </VCardTitle>

      <VCardText class="pb-0">
        <!-- Shift info -->
        <div
          v-if="shift"
          class="mb-4"
        >
          <div class="d-flex align-center gap-x-2 mb-1">
            <span class="text-h6">{{ shift.title ?? 'Shift' }}</span>
            <VChip
              v-if="shift.is_lead_role"
              color="warning"
              size="small"
            >
              Hoofdrol
            </VChip>
          </div>
          <div class="text-body-2 text-disabled">
            {{ shift.time_slot?.name }} — {{ shift.effective_start_time }}–{{ shift.effective_end_time }}
          </div>
          <div class="text-body-2 text-disabled">
            Capaciteit: {{ shift.filled_slots }}/{{ shift.slots_total }}
          </div>
        </div>

        <VDivider class="mb-4" />

        <!-- Error alert -->
        <VAlert
          v-if="assignError"
          type="error"
          variant="tonal"
          density="compact"
          closable
          class="mb-3"
          @click:close="assignError = null"
        >
          {{ assignError }}
        </VAlert>

        <!-- Search -->
        <VTextField
          v-model="searchQuery"
          prepend-inner-icon="tabler-search"
          placeholder="Zoek op naam of e-mail..."
          density="compact"
          hide-details
          clearable
          class="mb-3"
        />

        <!-- Filters -->
        <div class="d-flex align-center ga-3 mb-3">
          <VSwitch
            v-model="showOnlyAvailable"
            label="Alleen beschikbaar"
            density="compact"
            hide-details
            color="primary"
          />
          <VSelect
            v-model="selectedCrowdType"
            :items="crowdTypeOptions"
            label="Type"
            density="compact"
            hide-details
            clearable
            style="max-inline-size: 200px;"
          />
        </div>

        <!-- Loading -->
        <div v-if="isLoading">
          <VSkeletonLoader
            type="list-item-two-line"
            class="mb-1"
          />
          <VSkeletonLoader
            type="list-item-two-line"
            class="mb-1"
          />
          <VSkeletonLoader type="list-item-two-line" />
        </div>

        <!-- Person list -->
        <VList
          v-else-if="filteredPersons.length"
          density="compact"
          class="person-list overflow-y-auto"
          style="max-block-size: 400px;"
        >
          <template
            v-for="person in filteredPersons"
            :key="person.id"
          >
            <!-- Already assigned -->
            <VListItem
              v-if="person.already_assigned"
              disabled
              class="opacity-40"
            >
              <template #prepend>
                <VAvatar
                  size="36"
                  color="grey"
                  variant="tonal"
                >
                  <span class="text-caption">{{ getInitials(person.name) }}</span>
                </VAvatar>
              </template>
              <VListItemTitle class="text-decoration-line-through">
                {{ person.name }}
              </VListItemTitle>
              <VListItemSubtitle>
                <span class="text-success text-caption">Al toegewezen aan deze shift</span>
              </VListItemSubtitle>
            </VListItem>

            <!-- Conflict (unavailable) -->
            <VListItem
              v-else-if="!person.is_available && person.conflict"
              disabled
              class="opacity-50"
            >
              <template #prepend>
                <VAvatar
                  size="36"
                  color="grey"
                  variant="tonal"
                >
                  <span class="text-caption">{{ getInitials(person.name) }}</span>
                </VAvatar>
              </template>
              <VListItemTitle>{{ person.name }}</VListItemTitle>
              <VListItemSubtitle>
                <span>{{ person.email }}</span>
                <br>
                <span class="text-warning text-caption">
                  Ingepland bij "{{ person.conflict.section_name }}" — {{ person.conflict.time_slot_name }}
                </span>
              </VListItemSubtitle>
              <template #append>
                <VIcon
                  color="warning"
                  size="18"
                >
                  tabler-alert-triangle
                </VIcon>
              </template>
            </VListItem>

            <!-- Available -->
            <VListItem
              v-else
              :disabled="isAssigning"
              class="cursor-pointer"
              @click="handleAssign(person)"
            >
              <template #prepend>
                <VAvatar
                  size="36"
                  color="primary"
                  variant="tonal"
                >
                  <span class="text-caption">{{ getInitials(person.name) }}</span>
                </VAvatar>
              </template>
              <VListItemTitle>{{ person.name }}</VListItemTitle>
              <VListItemSubtitle>{{ person.email }}</VListItemSubtitle>
              <template #append>
                <VChip
                  v-if="person.crowd_type"
                  size="x-small"
                  variant="tonal"
                >
                  {{ person.crowd_type.name }}
                </VChip>
              </template>
            </VListItem>
          </template>
        </VList>

        <!-- Empty state -->
        <VCard
          v-else
          variant="outlined"
          class="text-center pa-6"
        >
          <VIcon
            icon="tabler-users-minus"
            size="36"
            class="mb-2 text-disabled"
          />
          <p class="text-body-2 text-disabled mb-0">
            {{ emptyReason }}
          </p>
        </VCard>
      </VCardText>

      <VCardActions>
        <VSpacer />
        <VBtn
          variant="text"
          @click="modelValue = false"
        >
          Sluiten
        </VBtn>
      </VCardActions>
    </VCard>
  </VDialog>

  <VSnackbar
    v-model="showSuccess"
    color="success"
    :timeout="2000"
  >
    {{ successName }} toegewezen
  </VSnackbar>
</template>
