import { clsx } from 'clsx';
import * as React from 'react';

import { Position } from '../common';
import { useDirection } from '../common/hooks';
import Tooltip from '../tooltip';

import { isTouchDevice } from './deviceDetection';

function clamp(from: number, to: number, value: number) {
  return Math.max(Math.min(to, value), from);
}

export interface Step {
  label: React.ReactNode;
  onClick?: () => void;
  hoverLabel?: React.ReactNode;
}

export interface StepperProps {
  steps: readonly Step[];
  activeStep?: number;
  className?: string;
  testId?: string;
}

/**
 * This component is considered user-unfriendly and inaccessible on its own and will likely be made internal in the future. Please use `FlowNavigation` instead.
 * @see https://storybook.wise.design/?path=/story/navigation-flownavigation--variants
 */
const Stepper = ({ steps, activeStep = 0, className, testId }: StepperProps) => {
  const { isRTL } = useDirection();

  if (steps.length === 0) {
    return null;
  }

  const activeStepIndex = clamp(0, steps.length - 1, activeStep);
  const stepPercentage = 1 / (steps.length - 1);
  const percentageCompleted = activeStepIndex / (steps.length - 1);

  const getProgressWidth = (): string => {
    if (percentageCompleted === 0) {
      return '0%';
    }
    /**
     * Progress bar starts with left/right (depends on rtl) shift `--progress-bar-start-shift` for hiding Progress bar's left and right borders
     * which are used for progress vertical delimiter.
     * When progress is completed, we need to add `--progress-bar-border-width` to the width to allow the right border be outside of the progress area.
     */
    return `calc(${percentageCompleted * 100}% + var(--progress-bar-start-shift) + var(--progress-bar-border-width))`;
  };

  const renderStep = (step: Step, index: number) => {
    const active = index === activeStepIndex;
    const clickable = step.onClick && !active;

    const labelButton = clickable ? (
      <button
        type="button"
        className="btn-unstyled tw-stepper__step-label"
        onClick={() => clickable && step.onClick?.()}
      >
        <small>{step.label}</small>
      </button>
    ) : (
      <span className="tw-stepper__step-label">{step.label}</span>
    );

    return (
      <li
        key={index}
        className={clsx(
          'hidden-xs',
          'tw-stepper__step',
          active ? 'np-text-body-default-bold tw-stepper__step--active' : 'np-text-body-default',
          clickable && 'tw-stepper__step--clickable',
          step.hoverLabel && 'tw-stepper__step--has-tooltip',
        )}
        aria-current={active ? 'step' : false}
        style={
          isRTL
            ? { right: `${index * stepPercentage * 100}%` }
            : { left: `${index * stepPercentage * 100}%` }
        }
      >
        {step.hoverLabel && !isTouchDevice() ? (
          <Tooltip position={Position.BOTTOM} label={step.hoverLabel}>
            {labelButton}
          </Tooltip>
        ) : (
          labelButton
        )}
      </li>
    );
  };

  return (
    <div className={clsx('tw-stepper', className)} data-testid={testId}>
      <div className="progress">
        <div
          className="progress-bar"
          style={{ width: getProgressWidth() }}
          data-testid="progress-bar"
        />
      </div>
      <ol className="tw-stepper-steps p-t-1 m-b-0">{steps.map(renderStep)}</ol>
    </div>
  );
};

export default Stepper;
