import type { Meta, StoryObj } from '@storybook/vue3-vite';
import * as lucideIcons from 'lucide-vue-next';
import { computed, ref, watch } from 'vue';
import { UiIcon } from '.';
import { UiButton } from '../UiButton';
import { UiInput } from '../UiInput';

/**
 * UiIcon renders a single icon from the Lucide icon set.
 * Use it for consistent sizing, styling, and accessibility semantics across the UI library.
 * @see https://lucide.dev/icons for available icons
 */
const meta: Meta<typeof UiIcon> = {
  title: 'Components/UiIcon',
  component: UiIcon,
  tags: ['autodocs'],
  argTypes: {
    name: {
      control: 'text',
      description:
        'Lucide icon name in kebab-case, e.g. `circle-help`, `chevron-down`.',
    },
    size: {
      control: 'number',
      description: 'Icon size in pixels. Defaults to 24.',
    },
    strokeWidth: {
      control: 'number',
      description: 'Stroke width. Defaults to 2.',
    },
    ariaLabel: {
      control: 'text',
      description:
        'Accessible label. If omitted, icon is treated as decorative.',
    },
  },
  args: {
    name: 'circle-help',
    size: 24,
    strokeWidth: 2,
    ariaLabel: 'Help',
  },
};

export default meta;
type Story = StoryObj<typeof UiIcon>;

const defaultTemplateSource = `<script setup lang="ts">
import { UiIcon } from '@aleph-alpha/ui-library'
</script>

<template>
  <div class="flex items-center gap-4">
    <UiIcon name="circle-help" aria-label="Help" class="text-foreground" />
    <UiIcon name="chevron-down" aria-label="Down" class="text-foreground" />
    <UiIcon name="check" aria-label="Check" class="text-foreground" />
  </div>
</template>`;

/**
 * Basic icon rendering with Lucide icons.
 * Use this as a starting point for choosing an icon and verifying size/color alignment in your layout.
 */
export const Default: Story = {
  render: (args) => ({
    components: { UiIcon },
    setup() {
      return { args };
    },
    template: `
      <div class="flex items-center gap-4">
        <UiIcon v-bind="args" class="text-foreground" />
        <UiIcon name="chevron-down" aria-label="Down" class="text-foreground" />
        <UiIcon name="check" aria-label="Check" class="text-foreground" />
      </div>
    `,
  }),
  parameters: {
    docs: { source: { code: defaultTemplateSource } },
  },
};

const sizesTemplateSource = `<script setup lang="ts">
import { UiIcon } from '@aleph-alpha/ui-library'
</script>

<template>
  <div class="flex items-center gap-4">
    <UiIcon name="star" :size="16" />
    <UiIcon name="star" :size="24" />
    <UiIcon name="star" :size="32" />
    <UiIcon name="star" :size="48" />
  </div>
</template>`;

/**
 * Icons can be rendered at different sizes using the `size` prop.
 */
export const Sizes: Story = {
  render: () => ({
    components: { UiIcon },
    template: `
      <div class="flex items-center gap-4">
        <UiIcon name="star" :size="16" />
        <UiIcon name="star" :size="24" />
        <UiIcon name="star" :size="32" />
        <UiIcon name="star" :size="48" />
      </div>
    `,
  }),
  parameters: {
    controls: { disable: true },
    docs: { source: { code: sizesTemplateSource } },
  },
};

const allIcons = Object.keys(lucideIcons)
  .filter(
    (name) =>
      /^[A-Z]/.test(name) &&
      name !== 'Icon' &&
      name !== 'LucideIcon' &&
      !name.endsWith('Icon'),
  )
  .sort((a, b) => a.localeCompare(b));

/**
 * Browse every Lucide icon available to `UiIcon`.
 * Duplicate `*Icon` aliases are filtered out so each icon appears once.
 */
export const IconLibrary: Story = {
  render: () => ({
    components: { UiButton, UiIcon, UiInput },
    setup() {
      const pageSize = 40;
      const page = ref(1);
      const searchedIcon = ref('');
      const normalizedSearch = computed(() =>
        searchedIcon.value.trim().toLowerCase(),
      );
      const filteredIcons = computed(() =>
        normalizedSearch.value
          ? allIcons.filter((icon) =>
              icon.toLowerCase().includes(normalizedSearch.value),
            )
          : allIcons,
      );
      const pageCount = computed(() =>
        Math.max(1, Math.ceil(filteredIcons.value.length / pageSize)),
      );
      const pageStart = computed(() => (page.value - 1) * pageSize);
      const pageEnd = computed(() =>
        Math.min(pageStart.value + pageSize, filteredIcons.value.length),
      );
      const resultStart = computed(() =>
        filteredIcons.value.length === 0 ? 0 : pageStart.value + 1,
      );
      const visibleIcons = computed(() =>
        filteredIcons.value.slice(pageStart.value, pageEnd.value),
      );

      watch(searchedIcon, () => {
        page.value = 1;
      });

      return {
        filteredIcons,
        page,
        pageCount,
        pageEnd,
        resultStart,
        searchedIcon,
        visibleIcons,
      };
    },
    template: `
      <div>
        <div class="mb-4 flex flex-wrap items-center justify-between gap-3">
          <div class="flex w-full items-center gap-1.5">
            <UiInput v-model="searchedIcon" id="search-icon" name="search-icon" placeholder="Search icons..." />
          </div>
          <p class="body-14-regular text-content-on-surface-muted">
            Showing {{ resultStart }}-{{ pageEnd }} of {{ filteredIcons.length }} icons from lucide-vue-next.
          </p>
          <div class="flex items-center gap-2">
            <UiButton variant="outline" size="sm" :disabled="page === 1" @click="page -= 1">
              Previous
            </UiButton>
            <span class="label-12-regular text-content-on-surface-muted">Page {{ page }} of {{ pageCount }}</span>
            <UiButton variant="outline" size="sm" :disabled="page === pageCount" @click="page += 1">
              Next
            </UiButton>
          </div>
        </div>
        <div class="grid grid-cols-2 gap-3 sm:grid-cols-3 md:grid-cols-4">
          <div
            v-for="icon in visibleIcons"
            :key="icon"
            class="flex min-w-0 items-center gap-3 rounded-md border border-border-surface-default bg-background-surface-floating p-5 text-content-on-surface-primary shadow-sm"
          >
            <UiIcon :name="icon" size="m" class="shrink-0" />
            <code class="truncate label-14-regular text-content-on-surface-muted">{{ icon }}</code>
          </div>
        </div>
        <p v-if="visibleIcons.length === 0" class="body-14-regular text-content-on-surface-muted">
          No icons found.
        </p>
      </div>
    `,
  }),
  parameters: {
    controls: { disable: true },
  },
};
