'use client';
/* eslint-disable jsdoc/require-jsdoc */

import * as React from 'react';
import { type HasChildren, type HasRootRef } from '../../types';
import { type CustomTouchEvent, Touch } from '../Touch/Touch';
import { type BaseGalleryProps } from './types';
import styles from './CarouselBase.module.css';

type GalleryViewPortProps = Pick<
  BaseGalleryProps,
  'slideWidth' | 'slideTestId' | 'slideRoleDescription' | 'slideLabel' | 'onChange'
> &
  HasRootRef<HTMLElement> &
  HasChildren & {
    onStart: (e: CustomTouchEvent) => void;
    onMoveX: (e: CustomTouchEvent) => void;
    onEnd: (e: CustomTouchEvent) => void;
    setSlideRef: (slideRef: HTMLDivElement | null, slideIndex: number) => void;
    layerRef?: React.Ref<HTMLDivElement>;
    slidesContainerId: string;
  };

const defaultSlideLabel = (index: number, slidesCount: number) => `${index + 1} из ${slidesCount}`;

export const CarouselViewPort = ({
  slideTestId,
  slideWidth,
  slideLabel = defaultSlideLabel,
  slideRoleDescription = 'Слайд',
  onChange,
  onStart,
  onMoveX,
  onEnd,
  getRootRef,
  layerRef,
  children,
  setSlideRef,
  slidesContainerId,
}: GalleryViewPortProps) => {
  const slidesCount = React.Children.count(children);

  const onSlideFocus = React.useCallback(
    (e: React.FocusEvent<HTMLDivElement>) => onChange?.(Number(e.currentTarget.dataset.index)),
    [onChange],
  );

  return (
    <Touch
      className={styles.viewport}
      onStartX={onStart}
      onMoveX={onMoveX}
      onEnd={onEnd}
      style={{ width: slideWidth === 'custom' ? '100%' : slideWidth }}
      noSlideClick
      getRootRef={getRootRef}
    >
      <div className={styles.layer} ref={layerRef} id={slidesContainerId}>
        {React.Children.map(children, (item: React.ReactNode, i: number) => (
          <div
            role="group"
            aria-roledescription={slideRoleDescription}
            aria-label={typeof slideLabel === 'function' ? slideLabel(i, slidesCount) : slideLabel}
            className={styles.slide}
            key={`slide-${i}`}
            data-testid={slideTestId?.(i)}
            ref={(el) => setSlideRef(el, i)}
            data-index={i}
            tabIndex={0}
            onFocus={onSlideFocus}
          >
            {item}
          </div>
        ))}
      </div>
    </Touch>
  );
};
