<template>
  <!-- CHECK-GRID VARIANT -->
  <div v-if="variant === 'check-grid'" class="cw-select-check-grid" :class="{ 'is-disabled': disabled }">
    <template v-if="normalizedOptions.length > 0">
      <label
        v-for="opt in normalizedOptions"
        :key="opt.value"
        class="cw-check-chip"
        :class="{ 'is-selected': isSelected(opt.value), 'is-disabled': disabled }"
        @click.prevent="toggleOption(opt.value)"
      >
        <span class="cw-check-box" :class="{ 'is-checked': isSelected(opt.value) }">
          <svg v-if="isSelected(opt.value)" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" class="cw-check-svg">
            <path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd"/>
          </svg>
        </span>
        <span v-if="opt.color" class="cw-color-dot" :style="{ background: opt.color }"></span>
        <span class="cw-chip-label">{{ opt.label }}</span>
      </label>
    </template>
    <div v-else class="cw-check-grid-empty">
      {{ placeholder || 'No options available' }}
    </div>
  </div>

  <!-- DROPDOWN VARIANT (Default) -->
  <div v-else class="cw-select" ref="selectRef">
    <!-- Trigger -->
    <div
      class="cw-select-trigger"
      :class="{ 'is-disabled': disabled, 'is-open': isOpen, 'is-multiple': multiple, 'has-tags': multiple && selectedOptionsList.length > 0 }"
      @click="togglePopover"
    >
      <!-- Single select value display -->
      <template v-if="!multiple">
        <div class="cw-select-single-val">
          <span v-if="selectedOption && selectedOption.color" class="cw-color-dot" :style="{ background: selectedOption.color }"></span>
          <span class="cw-select-value" :class="{ 'is-placeholder': !selectedOption }">
            {{ selectedOption ? selectedOption.label : (placeholder || 'Select Option') }}
          </span>
        </div>
      </template>

      <!-- Multi select value display -->
      <template v-else>
        <div class="cw-select-multi-container">
          <template v-if="selectedOptionsList.length > 0">
            <span
              v-for="opt in selectedOptionsList"
              :key="opt.value"
              class="cw-select-tag"
            >
              <span v-if="opt.color" class="cw-color-dot" :style="{ background: opt.color }"></span>
              <span class="cw-tag-label">{{ opt.label }}</span>
              <button
                type="button"
                class="cw-tag-remove"
                @click.stop="removeOption(opt.value)"
                title="Remove"
              >
                &times;
              </button>
            </span>
          </template>
          <span v-else class="cw-select-value is-placeholder">
            {{ placeholder || 'Select items...' }}
          </span>
        </div>
      </template>

      <div class="cw-select-actions">
        <button
          v-if="clearable && hasSelection && !disabled"
          type="button"
          class="cw-select-clear-btn"
          @click.stop="clearSelection"
          title="Clear selection"
        >
          &times;
        </button>
        <span class="cw-select-arrow">
          <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="cw-select-arrow-icon" :class="{ 'is-open': isOpen }">
            <path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5" />
          </svg>
        </span>
      </div>
    </div>

    <!-- Dropdown Popover -->
    <div v-if="isOpen" class="cw-select-popover" :class="`is-${placement}`">
      <!-- Search Input -->
      <div v-if="showSearch" class="cw-select-search-wrap">
        <svg xmlns="http://www.w3.org/2000/svg" class="cw-search-icon" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
          <path stroke-linecap="round" stroke-linejoin="round" d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/>
        </svg>
        <input
          ref="searchInputRef"
          type="text"
          v-model="searchQuery"
          class="cw-select-search-input"
          placeholder="Search..."
          @click.stop
        />
        <button v-if="searchQuery" class="cw-search-clear" @click.stop="searchQuery = ''">&times;</button>
      </div>

      <!-- Quick Action bar for multi select -->
      <div v-if="multiple && filteredOptions.filter(o => !o.group).length > 2" class="cw-select-quick-actions">
        <button type="button" class="cw-quick-btn" @click.stop="selectAll">Select All</button>
        <span class="cw-quick-sep">•</span>
        <button type="button" class="cw-quick-btn" @click.stop="clearSelection">Clear All</button>
      </div>

      <!-- Options List -->
      <div class="cw-select-options-list" v-if="filteredOptions.length > 0">
        <template v-for="(opt, idx) in filteredOptions" :key="opt.group ? 'grp-' + idx : (opt.value === null ? 'null' : opt.value)">
          <!-- Group Title Header -->
          <div v-if="opt.group" class="cw-select-group-header">
            {{ opt.group }}
          </div>
          <!-- Option Item -->
          <div
            v-else
            class="cw-select-option"
            :class="{ 'is-selected': isSelected(opt.value) }"
            @click.stop="toggleOption(opt.value)"
          >
            <div class="cw-option-left">
              <span v-if="multiple" class="cw-option-checkbox" :class="{ 'is-checked': isSelected(opt.value) }">
                <svg v-if="isSelected(opt.value)" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="11" height="11">
                  <path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd"/>
                </svg>
              </span>
              <span v-if="opt.color" class="cw-color-dot" :style="{ background: opt.color }"></span>
              <span class="cw-select-option-label">{{ opt.label }}</span>
            </div>
            <span v-if="!multiple && isSelected(opt.value)" class="cw-select-option-check">
              <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20" fill="currentColor" width="14" height="14">
                <path fill-rule="evenodd" d="M16.704 4.153a.75.75 0 01.143 1.052l-8 10.5a.75.75 0 01-1.127.075l-4.5-4.5a.75.75 0 011.06-1.06l3.894 3.893 7.48-9.817a.75.75 0 011.05-.143z" clip-rule="evenodd"/>
              </svg>
            </span>
          </div>
        </template>
      </div>
      <div v-else class="cw-select-no-options">
        {{ searchQuery ? 'No matching options' : 'No options available' }}
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onBeforeUnmount, nextTick } from 'vue';

const props = defineProps({
  modelValue: { type: [String, Number, Boolean, Array, Object], default: null },
  options: { type: Array, required: true },
  placeholder: { type: String, default: 'Select' },
  disabled: { type: Boolean, default: false },
  placement: { type: String, default: 'bottom' }, // 'bottom' or 'top'
  multiple: { type: Boolean, default: false },
  variant: { type: String, default: 'dropdown' }, // 'dropdown' | 'check-grid'
  searchable: { type: Boolean, default: null },
  clearable: { type: Boolean, default: false },
});

const emit = defineEmits(['update:modelValue', 'change']);

const isOpen = ref(false);
const searchQuery = ref('');
const selectRef = ref(null);
const searchInputRef = ref(null);

const normalizedOptions = computed(() => {
  if (!props.options) return [];
  return props.options.map(opt => {
    if (typeof opt === 'object' && opt !== null) {
      return opt;
    }
    return { value: opt, label: String(opt) };
  });
});

const showSearch = computed(() => {
  if (props.searchable !== null) return props.searchable;
  return normalizedOptions.value.filter(o => !o.group).length > 5;
});

const filteredOptions = computed(() => {
  if (!searchQuery.value.trim()) return normalizedOptions.value;
  const q = searchQuery.value.toLowerCase().trim();
  return normalizedOptions.value.filter(opt => {
    if (opt.group) return true;
    return String(opt.label).toLowerCase().includes(q);
  });
});

function isSelected(val) {
  if (props.multiple) {
    if (!Array.isArray(props.modelValue)) return false;
    return props.modelValue.some(v => String(v) === String(val));
  }
  return props.modelValue !== null && props.modelValue !== undefined && String(props.modelValue) === String(val);
}

const selectedOption = computed(() => {
  if (props.multiple) return null;
  return normalizedOptions.value.find(opt => !opt.group && isSelected(opt.value)) || null;
});

const selectedOptionsList = computed(() => {
  if (!props.multiple || !Array.isArray(props.modelValue)) return [];
  return props.modelValue
    .map(val => normalizedOptions.value.find(opt => !opt.group && String(opt.value) === String(val)))
    .filter(Boolean);
});

const hasSelection = computed(() => {
  if (props.multiple) {
    return Array.isArray(props.modelValue) && props.modelValue.length > 0;
  }
  return props.modelValue !== null && props.modelValue !== undefined && props.modelValue !== '';
});

function togglePopover() {
  if (props.disabled) return;
  isOpen.value = !isOpen.value;
  if (isOpen.value && showSearch.value) {
    nextTick(() => {
      searchInputRef.value?.focus();
    });
  }
}

function closePopover() {
  isOpen.value = false;
  searchQuery.value = '';
}

function toggleOption(val) {
  if (props.disabled) return;
  if (props.multiple) {
    let current = Array.isArray(props.modelValue) ? [...props.modelValue] : [];
    const idx = current.findIndex(v => String(v) === String(val));
    if (idx >= 0) {
      current.splice(idx, 1);
    } else {
      current.push(val);
    }
    emit('update:modelValue', current);
    emit('change', current);
  } else {
    emit('update:modelValue', val);
    emit('change', val);
    closePopover();
  }
}

function removeOption(val) {
  if (props.disabled || !props.multiple) return;
  let current = Array.isArray(props.modelValue) ? [...props.modelValue] : [];
  const idx = current.findIndex(v => String(v) === String(val));
  if (idx >= 0) {
    current.splice(idx, 1);
    emit('update:modelValue', current);
    emit('change', current);
  }
}

function clearSelection() {
  if (props.disabled) return;
  const newValue = props.multiple ? [] : null;
  emit('update:modelValue', newValue);
  emit('change', newValue);
}

function selectAll() {
  if (props.disabled || !props.multiple) return;
  const allVals = normalizedOptions.value.filter(o => !o.group).map(o => o.value);
  emit('update:modelValue', allVals);
  emit('change', allVals);
}

function handleClickOutside(e) {
  if (selectRef.value && !selectRef.value.contains(e.target)) {
    closePopover();
  }
}

onMounted(() => {
  document.addEventListener('click', handleClickOutside);
});

onBeforeUnmount(() => {
  document.removeEventListener('click', handleClickOutside);
});
</script>

<style scoped>
.cw-color-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  display: inline-block;
  flex-shrink: 0;
}

.cw-select {
  position: relative;
  width: 100%;
  font-family: inherit;
}

.cw-select-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
  min-height: 38px;
  padding: 5px 10px;
  background: var(--bg-surface, #ffffff);
  border: 1px solid var(--border-color, #e5e7eb);
  border-radius: 8px;
  font-size: 13px;
  color: var(--text-primary, #111827);
  cursor: pointer;
  user-select: none;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, background-color 0.15s ease;
  box-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.03);
}

.cw-select-trigger:hover:not(.is-disabled) {
  border-color: #93c5fd;
}

.cw-select-trigger.is-open {
  border-color: #2563eb;
  box-shadow: 0 0 0 3px rgba(37, 99, 235, 0.12);
}

.cw-select-trigger.is-disabled {
  background: var(--bg-hover, #f9fafb);
  color: var(--text-muted, #9ca3af);
  cursor: not-allowed;
  border-color: var(--border-color, #e5e7eb);
  opacity: 0.7;
}

.cw-select-single-val {
  display: flex;
  align-items: center;
  gap: 8px;
  overflow: hidden;
}

.cw-select-value {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  font-weight: 500;
  font-size: 13px;
}

.cw-select-value.is-placeholder {
  color: var(--text-muted, #9ca3af);
  font-weight: 400;
}

.cw-select-multi-container {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
  flex: 1;
  padding: 2px 0;
}

.cw-select-tag {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  background: #f3f4f6;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  padding: 2px 7px;
  font-size: 12px;
  font-weight: 500;
  color: #374151;
  line-height: 1.4;
  transition: all 0.12s ease;
}

.cw-select-tag:hover {
  background: #e5e7eb;
}

.cw-tag-label {
  max-width: 140px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cw-tag-remove {
  background: transparent;
  border: none;
  color: #9ca3af;
  font-size: 14px;
  line-height: 1;
  padding: 0;
  margin-left: 2px;
  cursor: pointer;
  border-radius: 50%;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 14px;
  height: 14px;
  transition: color 0.12s, background 0.12s;
}

.cw-tag-remove:hover {
  color: #ef4444;
  background: rgba(239, 68, 68, 0.12);
}

.cw-select-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-left: 6px;
}

.cw-select-clear-btn {
  background: transparent;
  border: none;
  color: #9ca3af;
  font-size: 14px;
  line-height: 1;
  cursor: pointer;
  padding: 2px 4px;
  border-radius: 4px;
}

.cw-select-clear-btn:hover {
  color: #4b5563;
  background: #f3f4f6;
}

.cw-select-arrow {
  display: flex;
  align-items: center;
  color: var(--text-muted, #9ca3af);
}

.cw-select-arrow-icon {
  width: 12px;
  height: 12px;
  transition: transform 0.15s ease;
}

.cw-select-arrow-icon.is-open {
  transform: rotate(180deg);
}

/* Dropdown popover */
.cw-select-popover {
  position: absolute;
  left: 0;
  right: 0;
  background: var(--bg-surface, #ffffff);
  border: 1px solid var(--border-color, #e5e7eb);
  border-radius: 8px;
  box-shadow: 0 10px 25px -5px rgba(0, 0, 0, 0.1), 0 8px 10px -6px rgba(0, 0, 0, 0.04);
  z-index: 1050;
  max-height: 260px;
  overflow-y: auto;
  padding: 4px;
}

.cw-select-popover.is-bottom {
  top: calc(100% + 4px);
  animation: slideDown 0.12s cubic-bezier(0.16, 1, 0.3, 1);
}

.cw-select-popover.is-top {
  bottom: calc(100% + 4px);
  animation: slideUp 0.12s cubic-bezier(0.16, 1, 0.3, 1);
}

@keyframes slideDown {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}

@keyframes slideUp {
  from { opacity: 0; transform: translateY(4px); }
  to { opacity: 1; transform: translateY(0); }
}

/* Search input */
.cw-select-search-wrap {
  position: relative;
  display: flex;
  align-items: center;
  padding: 4px 6px 6px;
  border-bottom: 1px solid #f3f4f6;
  margin-bottom: 4px;
}

.cw-search-icon {
  position: absolute;
  left: 12px;
  width: 14px;
  height: 14px;
  color: #9ca3af;
  pointer-events: none;
}

.cw-select-search-input {
  width: 100%;
  height: 30px;
  padding: 0 24px 0 28px;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 6px;
  font-size: 12px;
  color: #111827;
  outline: none;
  transition: border-color 0.12s;
}

.cw-select-search-input:focus {
  border-color: #2563eb;
  background: #ffffff;
}

.cw-search-clear {
  position: absolute;
  right: 12px;
  background: transparent;
  border: none;
  color: #9ca3af;
  font-size: 14px;
  cursor: pointer;
  padding: 0;
}

/* Quick Actions */
.cw-select-quick-actions {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px 6px;
  font-size: 11px;
}

.cw-quick-btn {
  background: transparent;
  border: none;
  color: #2563eb;
  font-size: 11px;
  font-weight: 500;
  cursor: pointer;
  padding: 0;
}

.cw-quick-btn:hover {
  text-decoration: underline;
}

.cw-quick-sep {
  color: #d1d5db;
}

.cw-select-options-list {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.cw-select-option {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 7px 10px;
  font-size: 13px;
  color: var(--text-secondary, #374151);
  border-radius: 6px;
  cursor: pointer;
  user-select: none;
  transition: background 0.1s ease, color 0.1s ease;
}

.cw-option-left {
  display: flex;
  align-items: center;
  gap: 8px;
  overflow: hidden;
}

.cw-select-option-label {
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cw-option-checkbox {
  width: 16px;
  height: 16px;
  border: 1px solid #d1d5db;
  border-radius: 4px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  background: #ffffff;
  transition: all 0.12s ease;
}

.cw-option-checkbox.is-checked {
  background: #2563eb;
  border-color: #2563eb;
  color: #ffffff;
}

.cw-select-option:hover {
  background: var(--bg-hover, #f3f4f6);
  color: var(--text-primary, #111827);
}

.cw-select-option.is-selected {
  background: var(--active-bg, #eff6ff);
  color: var(--active-text, #1d4ed8);
  font-weight: 600;
}

.cw-select-option-check {
  color: var(--active-text, #2563eb);
  display: flex;
  align-items: center;
  margin-left: 8px;
}

.cw-select-no-options {
  padding: 12px;
  font-size: 12px;
  color: var(--text-muted, #9ca3af);
  text-align: center;
}

.cw-select-group-header {
  padding: 8px 10px 4px;
  font-size: 10px;
  font-weight: 700;
  text-transform: uppercase;
  color: var(--text-muted, #9ca3af);
  letter-spacing: 0.05em;
  user-select: none;
}

/* CHECK-GRID VARIANT STYLING */
.cw-select-check-grid {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  max-height: 150px;
  overflow-y: auto;
  padding: 10px;
  background: #ffffff;
  border: 1px solid var(--border-color, #e5e7eb);
  border-radius: 8px;
}

.cw-select-check-grid.is-disabled {
  background: #f9fafb;
  opacity: 0.7;
  pointer-events: none;
}

.cw-check-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  font-weight: 500;
  color: #374151;
  background: #f9fafb;
  border: 1px solid #e5e7eb;
  border-radius: 20px;
  padding: 4px 10px 4px 8px;
  cursor: pointer;
  user-select: none;
  transition: all 0.15s ease;
}

.cw-check-chip:hover {
  background: #f3f4f6;
  border-color: #d1d5db;
}

.cw-check-chip.is-selected {
  background: #eff6ff;
  border-color: #93c5fd;
  color: #1d4ed8;
  font-weight: 600;
}

.cw-check-box {
  width: 14px;
  height: 14px;
  border: 1px solid #d1d5db;
  border-radius: 3px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: #ffffff;
  transition: all 0.12s ease;
}

.cw-check-box.is-checked {
  background: #2563eb;
  border-color: #2563eb;
  color: #ffffff;
}

.cw-check-svg {
  width: 10px;
  height: 10px;
}

.cw-chip-label {
  line-height: 1.2;
}

.cw-check-grid-empty {
  font-size: 12px;
  color: #9ca3af;
  padding: 4px 0;
}
</style>

