<script setup lang="ts">
import { computed, watch } from 'vue'
import { useI18n } from 'vue-i18n'

interface ServiceItem {
  id: string
  code: string
  name: string
}

const props = defineProps<{
  services: ServiceItem[]
  serviceRows?: string[][]
  modelValue: string[]
}>()

const emit = defineEmits<{
  (e: 'update:modelValue', value: string[]): void
}>()
const { t } = useI18n()

const selectedSet = computed(() => new Set(props.modelValue))
const serviceById = computed(() => new Map(props.services.map(item => [item.id, item])))
const firstRowIds = computed(() => {
  const rows = Array.isArray(props.serviceRows) ? props.serviceRows : []
  if (rows.length === 0) return [] as string[]
  const firstRow = Array.isArray(rows[0]) ? rows[0] : []
  return firstRow.filter(id => serviceById.value.has(id))
})
const firstRowIdSet = computed(() => new Set(firstRowIds.value))
const groupedRows = computed(() => {
  const rows = Array.isArray(props.serviceRows) ? props.serviceRows : []
  if (rows.length === 0) return [] as ServiceItem[][]

  const used = new Set<string>()
  const grouped = rows
    .map(row => row.map(id => serviceById.value.get(id)).filter((item): item is ServiceItem => Boolean(item)))
    .map(row => row.filter(item => {
      if (used.has(item.id)) return false
      used.add(item.id)
      return true
    }))
    .filter(row => row.length > 0)

  const leftovers = props.services.filter(item => !used.has(item.id))
  if (leftovers.length > 0) grouped.push(leftovers)
  return grouped
})

const toggleService = (id: string, checked: boolean) => {
  const next = new Set(props.modelValue)
  if (checked) {
    if (firstRowIdSet.value.has(id)) {
      firstRowIds.value.forEach(firstId => next.delete(firstId))
    }
    next.add(id)
  } else {
    next.delete(id)
  }
  emit('update:modelValue', props.services.map(item => item.id).filter(itemId => next.has(itemId)))
}

const isFirstRowDisabled = (id: string) => {
  if (!firstRowIdSet.value.has(id)) return false
  for (const selectedId of props.modelValue) {
    if (selectedId !== id && firstRowIdSet.value.has(selectedId)) return true
  }
  return false
}

watch(
  () => [props.modelValue, firstRowIds.value] as const,
  () => {
    const firstSelected = props.modelValue.filter(id => firstRowIdSet.value.has(id))
    if (firstSelected.length <= 1) return
    const keepId = firstRowIds.value.find(id => firstSelected.includes(id)) || firstSelected[0]
    const next = props.modelValue.filter(id => !firstRowIdSet.value.has(id) || id === keepId)
    emit('update:modelValue', next)
  },
  { immediate: true, deep: true }
)

const clearAll = () => {
  emit('update:modelValue', [])
}
</script>

<template>
  <div class="rounded-lg border bg-card p-2.5 shadow-sm">
    <div class="mb-1 flex items-center justify-between gap-2">
      <div class="flex min-w-0 items-center gap-1.5">
        <label class="block shrink-0 text-sm font-semibold leading-none text-slate-900">{{ t('serviceSelector.title') }}</label>
        <span class="min-w-0 text-xs leading-5 text-muted-foreground">{{ t('serviceSelector.titleHint') }}</span>
      </div>
      <button
        type="button"
        class="cursor-pointer h-6 rounded-md border px-2 text-[13px] text-muted-foreground transition hover:bg-accent"
        @click="clearAll"
      >
        {{ t('serviceSelector.clear') }}
      </button>
    </div>
    <div class="rounded-md border p-1.5">
      <div v-if="groupedRows.length > 0" class="flex flex-col gap-1.5">
        <div
          v-for="(row, rowIndex) in groupedRows"
          :key="`service-row-${rowIndex}`"
          class="flex flex-wrap items-start gap-1 border-b border-slate-200 pb-1.5 last:border-b-0 last:pb-0"
        >
          <label
            v-for="item in row"
            :key="item.id"
            :class="[
              'inline-flex w-fit max-w-full items-start gap-1.5 rounded-md border px-2 py-1 text-[11px] leading-4 transition',
              isFirstRowDisabled(item.id)
                ? 'cursor-not-allowed border-slate-300 bg-slate-100/80 text-slate-400 opacity-80'
                : 'cursor-pointer hover:bg-muted/60'
            ]"
          >
            <input
              type="checkbox"
              :class="[
                'mt-0.5',
                isFirstRowDisabled(item.id) ? 'cursor-not-allowed accent-slate-300' : 'cursor-pointer'
              ]"
              :checked="selectedSet.has(item.id)"
              :disabled="isFirstRowDisabled(item.id)"
              @change="toggleService(item.id, ($event.target as HTMLInputElement).checked)"
            />
            <span class="text-muted-foreground shrink-0">{{ item.code }}</span>
            <span class="text-foreground break-words">{{ item.name }}</span>
          </label>
        </div>
      </div>
      <div v-if="props.services.length === 0" class="px-2 py-4 text-center text-xs text-muted-foreground">
        {{ t('serviceSelector.empty') }}
      </div>
    </div>
  </div>
</template>
