import type { FC } from 'react';
import React, { useEffect, useState } from 'react';
import cx from 'classnames';
import { Popover } from '../popover';
import { SkeletonLoader } from '../skeletonLoader';
import {
    PaginationArrow,
    PaginationMessage,
    PaginationNavigationSection,
    PaginationPageSizeSection,
} from './components';
import { CLASS_NAME_POPOVER, CLASS_NAME } from './constants';
import { getTotalPages } from './utils';
import type { PaginationProps } from './types';

/**
 * Pagination is a navigation component that splits the content of a table or a list of objects into several distinct pages.
 *
 * @type molecule
 * @status live
 * @tags navigation
 */
export const Pagination: FC<PaginationProps> = ({
    currentPage,
    pageSizeOptions,
    pageSize,
    totalCount,
    onChange,
    onSetPageSize,
    className,
    style,
    disabled = false,
    loading = false,
    variant = 'compact',
    testId = CLASS_NAME,
    menuPlacement = 'bottom',
}) => {
    const totalPages = getTotalPages(totalCount, pageSize);
    const page = currentPage >= 0 ? currentPage : 0;
    const [show, setShow] = useState<boolean | undefined>(undefined);

    useEffect(() => {
        if (show === false) setShow(undefined);
    }, [show]);

    const handleOnChange = (nextPage: number) => {
        onChange(nextPage);
        setShow(false);
    };

    const handleOnSetPageSize = (size: number) => {
        onSetPageSize(size);
        setShow(false);
    };

    const renderFirstArrow = () => {
        if (variant === 'compact') return null;

        if (loading) {
            return <SkeletonLoader shape="circle" height={24} width={24} />;
        }

        return (
            <PaginationArrow
                type="first"
                disabled={disabled || page === 0}
                onClick={() => handleOnChange(0)}
            />
        );
    };

    const renderPrevArrow = () => {
        if (loading)
            return <SkeletonLoader className="prev" shape="circle" height={24} width={24} />;

        return (
            <PaginationArrow
                type="prev"
                disabled={disabled || page === 0}
                onClick={() => handleOnChange(page - 1)}
            />
        );
    };

    const renderMessage = () => {
        if (loading) return <SkeletonLoader shape="line" height={24} width={100} />;

        return (
            <PaginationMessage
                disabled={disabled}
                currentPage={page}
                pageSize={pageSize}
                totalCount={totalCount}
            />
        );
    };

    const renderNextArrow = () => {
        if (loading)
            return <SkeletonLoader className="next" shape="circle" height={24} width={24} />;

        return (
            <PaginationArrow
                type="next"
                disabled={disabled || page >= totalPages - 1}
                onClick={() => handleOnChange(page + 1)}
            />
        );
    };

    const renderLastArrow = () => {
        if (variant === 'compact') return null;

        if (loading) return <SkeletonLoader shape="circle" height={24} width={24} />;

        return (
            <PaginationArrow
                type="last"
                disabled={disabled || page >= totalPages - 1}
                onClick={() => handleOnChange(totalPages - 1)}
            />
        );
    };

    return (
        <div className={cx(CLASS_NAME, className, { disabled })} style={style} data-testid={testId}>
            {renderFirstArrow()}

            {renderPrevArrow()}

            <Popover
                id={CLASS_NAME_POPOVER}
                placement={menuPlacement}
                show={disabled ? false : show}
                content={
                    <div className={CLASS_NAME_POPOVER}>
                        <PaginationPageSizeSection
                            pageSize={pageSize}
                            pageSizeOptions={pageSizeOptions}
                            onSetPageSize={handleOnSetPageSize}
                        />

                        {variant === 'compact' && (
                            <PaginationNavigationSection
                                disabled={disabled}
                                onChange={handleOnChange}
                                currentPage={currentPage}
                                totalPages={totalPages}
                            />
                        )}
                    </div>
                }
            >
                {renderMessage()}
            </Popover>

            {renderNextArrow()}

            {renderLastArrow()}
        </div>
    );
};
