<template>
  <div class="stepper">
    <div class="stepper-header">
      <div
        v-for="(step, index) of steps"
        :key="index"
        class="stepper-header--step"
        :class="{ clickable }"
      >
        <div
          class="stepper-header--indicator"
          :class="stepIndicator(step, index)"
          @click="onStepClick(index)"
        >
          <Check v-if="step.stepComplete" />
          <span v-else>{{ index + 1 }}</span>
        </div>
        <div @click="onStepClick(index)">{{ step.stepLabel }}</div>
        <hr v-if="index < steps.length - 1" class="stepper-header--separator" />
      </div>
    </div>
    <div class="stepper-body">
      <component
        :is="currentStepObject?.stepNode"
        v-if="currentStepObject"
        :key="currentStep"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { Check } from 'lucide-vue-next';
import type { Slots } from 'vue';
import { computed, ComputedRef, isVNode, useSlots, VNode } from 'vue';

const props = withDefaults(
  defineProps<{ currentStep: number; clickable: boolean }>(),
  {
    currentStep: 0,
    clickable: false,
  },
);
const slots: Slots = useSlots();

const emit = defineEmits(['stepClick']);

interface Step {
  stepNode: VNode;
  stepComplete: boolean;
  stepLabel: string;
}

const steps: ComputedRef<Step[]> = computed(() => {
  if (slots.default) {
    return slots
      ?.default()
      .filter((slot) => {
        return isVNode(slot) && (slot.type as any).__name === 'BmsStep';
      })
      .map((step) => ({
        stepComplete: step.props
          ? step.props.stepComplete || step.props['step-complete']
          : false,
        stepLabel: step.props
          ? step.props.stepLabel || step.props['step-label']
          : '',
        stepNode: step,
      }));
  }
  return [];
});

const currentStepObject: ComputedRef<Step | null> = computed(() => {
  if (steps.value.length > 0) {
    return steps.value[props.currentStep];
  }
  return null;
});

const stepIndicator = (step: Step, stepIndex: number) => {
  if (stepIndex === props.currentStep) {
    return {
      active: true,
    };
  }
  if (step.stepComplete) {
    return {
      complete: true,
    };
  }
  return '';
};

const onStepClick = (number: number) => {
  if (props.clickable) emit('stepClick', number);
};
</script>

<style lang="scss" scoped>
.stepper {
  &-header {
    display: flex;
    justify-content: center;
    align-items: center;
    top: 0;
    padding: 2em 0;

    &::before {
      content: '';
      display: block;
      width: 80%;
      left: 10%;
      position: absolute;
      z-index: -1;
      bottom: 0;
      height: 2em;
      border-radius: 100%;
      box-shadow: 0 0 16px rgba(black, 0.16);
      opacity: 0;
      transition: opacity 0.2s linear;
    }

    &::after {
      content: '';
      display: block;
      position: absolute;
      top: 0;
      left: 0;
      width: 100%;
      height: 100%;
      background: transparent;
      z-index: -1;
    }

    &--step {
      display: flex;
      justify-content: center;
      align-items: center;
      margin: 0 10px;

      &:first-child {
        margin: 0 10px 0 0;
      }

      &:last-child {
        margin: 0;
      }

      &.clickable:hover {
        div {
          cursor: pointer;
        }
      }
    }

    &--indicator {
      width: 30px;
      height: 30px;
      display: flex;
      align-items: center;
      justify-content: center;
      background-color: light-dark(var(--bms-main-50), var(--bms-main-140));
      color: light-dark(var(--bms-font-color), var(--bms-main-10));
      border-radius: 50%;
      font-weight: bold;
      margin-right: 10px;

      &.active {
        border: none;
        background-color: var(--bms-main-100);
        color: var(--bms-white);
      }

      &.complete {
        border: none;
        background-color: var(--bms-success-color);
        color: var(--bms-white);
        font-size: 20px;
      }
    }

    &--separator {
      width: 30px;
      margin-left: 10px;
      border: 0;
      border-top: 1px solid light-dark(var(--bms-grey-25), var(--bms-grey-100));
    }
  }

  &-body {
    margin: 10px 10px 0 10px;
  }
}
</style>
