<script setup lang="ts">
import { computed, ref } from "vue";
import Label from "../ui/Label.vue";
import { useTranslations } from "../../composables/useTranslations";
import type { FieldDefinition } from "./types";

const props = defineProps<{
  field: FieldDefinition;
  modelValue?: unknown;
  error?: string;
}>();

const emit = defineEmits<{
  "update:modelValue": [value: string[]];
}>();

const { t } = useTranslations();

const search = ref("");

const selected = computed<string[]>(() => {
  if (!Array.isArray(props.modelValue)) return [];
  return (props.modelValue as unknown[]).flatMap((v) => {
    if (typeof v === "object" && v !== null) {
      const name = (v as Record<string, unknown>).name;
      return name != null ? [String(name)] : [];
    }
    const s = String(v);
    return s !== "" ? [s] : [];
  });
});

const allOptions = computed<Array<{ value: string; label: string }>>(() => {
  const opts = props.field.options ?? {};
  return Object.entries(opts).map(([value, label]) => ({
    value: String(value),
    label: String(label),
  }));
});

const filteredOptions = computed(() => {
  const q = search.value.toLowerCase().trim();
  if (!q) return allOptions.value;
  return allOptions.value.filter(
    (opt) =>
      opt.value.toLowerCase().includes(q) ||
      opt.label.toLowerCase().includes(q),
  );
});

function isChecked(value: string): boolean {
  return selected.value.includes(value);
}

function toggle(value: string, checked: boolean): void {
  if (checked) {
    emit("update:modelValue", [...selected.value, value]);
  } else {
    emit(
      "update:modelValue",
      selected.value.filter((v) => v !== value),
    );
  }
}

function selectAll(): void {
  const current = new Set(selected.value);
  for (const opt of filteredOptions.value) {
    current.add(opt.value);
  }
  emit("update:modelValue", Array.from(current));
}

function deselectAll(): void {
  const filtered = new Set(filteredOptions.value.map((o) => o.value));
  emit(
    "update:modelValue",
    selected.value.filter((v) => !filtered.has(v)),
  );
}
</script>

<template>
  <div class="space-y-3">
    <!-- Search + select-all controls -->
    <div class="flex items-center gap-3">
      <input
        v-model="search"
        type="text"
        :placeholder="t('builder.permissions.search')"
        class="border-input bg-background ring-offset-background focus-visible:ring-ring flex h-9 flex-1 rounded-md border px-3 py-1 text-sm shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-1"
      />
      <button
        type="button"
        class="text-sm text-muted-foreground hover:text-foreground transition-colors"
        @click="selectAll"
      >
        {{ t("builder.permissions.select_all") }}
      </button>
      <button
        type="button"
        class="text-sm text-muted-foreground hover:text-foreground transition-colors"
        @click="deselectAll"
      >
        {{ t("builder.permissions.deselect_all") }}
      </button>
    </div>

    <!-- Permissions grid -->
    <div
      v-if="filteredOptions.length > 0"
      class="grid grid-cols-1 gap-2 sm:grid-cols-2 lg:grid-cols-3"
    >
      <div
        v-for="opt in filteredOptions"
        :key="opt.value"
        class="flex items-center gap-2"
      >
        <input
          :id="`${field.name}_${opt.value}`"
          type="checkbox"
          :checked="isChecked(opt.value)"
          :disabled="field.readonly"
          class="h-4 w-4 shrink-0 cursor-pointer rounded-sm border border-input [accent-color:hsl(var(--primary))] disabled:cursor-not-allowed disabled:opacity-50"
          @change="
            toggle(opt.value, ($event.target as HTMLInputElement).checked)
          "
        />
        <Label
          :for="`${field.name}_${opt.value}`"
          class="font-normal cursor-pointer"
        >
          {{ opt.label }}
        </Label>
      </div>
    </div>

    <p v-else class="text-sm text-muted-foreground">
      {{
        search
          ? "No permissions match your search."
          : "No permissions available."
      }}
    </p>
  </div>
</template>
