<script setup>
import { computed, ref, watch } from 'vue';

import { ArrowDown, Search } from '@element-plus/icons-vue';
import {
  ElButton,
  ElDropdown,
  ElDropdownItem,
  ElDropdownMenu,
  ElIcon,
  ElInput,
} from 'element-plus';

import { hasPermission } from '#/api/common/hasPermission.ts';
import { $t } from '#/locales';

const props = defineProps({
  buttons: {
    type: Array,
    default: () => [],
    validator: (value) => {
      return value.every((button) => {
        return (
          typeof button.text === 'string' &&
          (button.key || typeof button.key === 'string')
        );
      });
    },
  },
  maxVisibleButtons: {
    type: Number,
    default: 3,
  },
  initialValue: {
    type: String,
    default: '',
  },
  searchPlaceholder: {
    type: String,
    default: $t('common.searchPlaceholder'),
  },
});

const emit = defineEmits(['search', 'buttonClick', 'reset']);

const searchValue = ref(props.initialValue);

watch(
  () => props.initialValue,
  (value) => {
    searchValue.value = value;
  },
);

const filterButtonsByPermission = (buttons) => {
  return buttons.filter((button) => {
    return !button.permission || hasPermission([button.permission]);
  });
};

const visibleButtons = computed(() => {
  return filterButtonsByPermission(props.buttons).slice(
    0,
    props.maxVisibleButtons,
  );
});

const dropdownButtons = computed(() => {
  return filterButtonsByPermission(props.buttons).slice(
    props.maxVisibleButtons,
  );
});

const emitButtonEvent = (payload) => {
  emit('buttonClick', payload);
};

const handleSearch = () => {
  emit('search', searchValue.value);
};

const handleReset = () => {
  searchValue.value = '';
  emit('reset');
  emit('search', '');
};

defineExpose({
  reset: handleReset,
});

const handleButtonClick = (button) => {
  emitButtonEvent({
    type: 'button',
    key: button.key,
    button,
    data: button.data,
  });
};

const handleDropdownClick = (button) => {
  emitButtonEvent({
    type: 'dropdown',
    key: button.key,
    button,
    data: button.data,
  });
};
</script>

<template>
  <div class="custom-header">
    <div class="header-left">
      <div class="search-group">
        <ElInput
          v-model="searchValue"
          :placeholder="searchPlaceholder"
          class="search-input"
          clearable
          @keyup.enter="handleSearch"
        >
          <template #prefix>
            <ElIcon class="search-prefix">
              <Search />
            </ElIcon>
          </template>
        </ElInput>
        <ElButton type="primary" auto-insert-space @click="handleSearch">
          {{ $t('button.query') }}
        </ElButton>
        <ElButton auto-insert-space @click="handleReset">
          {{ $t('button.reset') }}
        </ElButton>
        <div v-if="$slots.middle" class="search-middle">
          <slot name="middle"></slot>
        </div>
      </div>
    </div>

    <div
      v-if="visibleButtons.length > 0 || dropdownButtons.length > 0"
      class="header-right"
    >
      <template
        v-for="(button, index) in visibleButtons"
        :key="button.key || index"
      >
        <ElButton
          :type="button.type || 'default'"
          :icon="button.icon"
          :disabled="button.disabled"
          :loading="button.loading"
          v-access:code="button.permission"
          @click="handleButtonClick(button)"
        >
          {{ button.text }}
        </ElButton>
      </template>

      <ElDropdown
        v-if="dropdownButtons.length > 0"
        @command="handleDropdownClick"
      >
        <ElButton>
          {{ $t('button.more') }}
          <ElIcon class="el-icon--right"><ArrowDown /></ElIcon>
        </ElButton>
        <template #dropdown>
          <ElDropdownMenu>
            <ElDropdownItem
              v-for="button in dropdownButtons"
              :key="button.key"
              :command="button"
              :disabled="button.disabled"
            >
              <ElIcon v-if="button.icon">
                <component :is="button.icon" />
              </ElIcon>
              <span class="dropdown-label">{{ button.text }}</span>
            </ElDropdownItem>
          </ElDropdownMenu>
        </template>
      </ElDropdown>
    </div>
  </div>
</template>

<style scoped>
.custom-header {
  display: flex;
  gap: 16px;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}

.header-left,
.header-right {
  display: flex;
  align-items: center;
  min-width: 0;
}

.header-left {
  flex: 1;
}

.search-group {
  display: flex;
  flex: 1;
  flex-wrap: wrap;
  gap: 12px;
  align-items: center;
}

.search-middle {
  display: flex;
  align-items: center;
  min-width: 0;
}

.search-input {
  width: min(360px, 100%);
}

.search-input :deep(.el-input__wrapper) {
  min-height: 40px;
  background: hsl(var(--surface-contrast-soft) / 92%);
  border-radius: 14px;
  box-shadow:
    inset 0 1px 0 hsl(var(--glass-border) / 44%),
    0 10px 24px -24px hsl(var(--foreground) / 24%);
}

.search-input :deep(.el-input__wrapper:hover),
.search-input :deep(.el-input__wrapper.is-focus) {
  background: hsl(var(--surface-subtle) / 98%);
  box-shadow:
    inset 0 1px 0 hsl(var(--glass-border) / 56%),
    0 0 0 3px hsl(var(--primary) / 8%),
    0 12px 24px -24px hsl(var(--foreground) / 24%);
}

.search-prefix {
  color: hsl(var(--text-muted));
}

.header-right {
  flex-shrink: 0;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: flex-end;
}

.header-right :deep(.el-button),
.search-group :deep(.el-button) {
  min-width: 64px;
  height: 32px;
  min-height: 32px;
  padding-inline: 18px;
  border-color: transparent;
  border-radius: 10px;
  box-shadow: none;
}

.header-right :deep(.el-button:not(.el-button--primary)),
.search-group :deep(.el-button:not(.el-button--primary)) {
  color: hsl(var(--text-strong));
  background: hsl(var(--surface-contrast-soft) / 86%);
  border-color: transparent;
  box-shadow:
    inset 0 1px 0 hsl(var(--glass-border) / 34%),
    0 10px 24px -24px hsl(var(--foreground) / 20%);
}

.header-right :deep(.el-button--primary),
.search-group :deep(.el-button--primary) {
  box-shadow: 0 16px 28px -22px hsl(var(--primary) / 48%);
}

.dropdown-label {
  margin-left: 8px;
}

@media (max-width: 768px) {
  .custom-header {
    flex-direction: column;
    gap: 12px;
    align-items: stretch;
  }

  .header-right {
    justify-content: flex-start;
  }

  .search-middle {
    width: 100%;
  }

  .search-input {
    width: 100%;
  }
}
</style>
