// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

import { MemoryRouter } from "react-router-dom";
import { TabList } from "@coreai-ds/react-components";
import * as React from "react";
import type { TabProps as CoreAITabProps } from "@coreai-ds/react-components";
import type { NavLinkProps } from "react-router-dom";
import type { LinkProps as RouterLinkProps } from "react-router-dom";
import type { NavLinkProps as RouterNavLinkProps } from "react-router-dom";
import { NavLink as RouterNavLink } from "react-router-dom";
import { Tab as CoreAITab } from "@coreai-ds/react-components";

type TabRouterProps = Omit<NavLinkProps, 'children' | 'className' | 'style'>;

type TabLinkProps = Omit<CoreAITabProps, keyof TabRouterProps | 'as' | 'value'> & TabRouterProps;

const routerLinkPropNames = [
    'defaultShouldRevalidate',
    'discover',
    'download',
    'hrefLang',
    'mask',
    'media',
    'ping',
    'prefetch',
    'preventScrollReset',
    'referrerPolicy',
    'relative',
    'rel',
    'reloadDocument',
    'replace',
    'state',
    'target',
    'to',
    'type',
    'viewTransition',
] as const satisfies readonly (keyof RouterLinkProps)[];

type RouterLinkSlotProps = Pick<RouterLinkProps, (typeof routerLinkPropNames)[number]>;

type RouterNavLinkSlotProps = RouterLinkSlotProps & Pick<RouterNavLinkProps, 'caseSensitive' | 'end'>;

type SlotRootProps = React.ComponentPropsWithoutRef<'a'> & {
    as?: unknown;
    disabled?: boolean;
    value?: unknown;
};

type ComponentProps<T> = Omit<T, keyof RouterLinkSlotProps>;

function splitRouterLinkProps<T extends RouterLinkSlotProps>(props: T): [
    RouterLinkSlotProps,
    ComponentProps<T>
] {
    const routerProps: Record<string, unknown> = {};
    const componentProps: Record<string, unknown> = { ...props };
    for (const name of routerLinkPropNames) {
        routerProps[name] = props[name];
        delete componentProps[name];
    }
    return [routerProps as RouterLinkSlotProps, componentProps as ComponentProps<T>];
}

function useStableRouterLinkProps(props: RouterLinkSlotProps): RouterLinkSlotProps {
    const { defaultShouldRevalidate, discover, download, hrefLang, mask, media, ping, prefetch, preventScrollReset, referrerPolicy, relative, rel, reloadDocument, replace, state, target, to, type, viewTransition, } = props;
    return React.useMemo(() => ({
        defaultShouldRevalidate,
        discover,
        download,
        hrefLang,
        mask,
        media,
        ping,
        prefetch,
        preventScrollReset,
        referrerPolicy,
        relative,
        rel,
        reloadDocument,
        replace,
        state,
        target,
        to,
        type,
        viewTransition,
    }), [
        defaultShouldRevalidate,
        discover,
        download,
        hrefLang,
        mask,
        media,
        ping,
        prefetch,
        preventScrollReset,
        referrerPolicy,
        relative,
        rel,
        reloadDocument,
        replace,
        state,
        target,
        to,
        type,
        viewTransition,
    ]);
}

function useRouterNavLinkSlot<T extends RouterNavLinkSlotProps>(props: T, mode: 'anchor' | 'tab' = 'anchor'): [
    React.ForwardRefExoticComponent<SlotRootProps & React.RefAttributes<HTMLAnchorElement>>,
    Omit<ComponentProps<T>, 'caseSensitive' | 'end'>
] {
    const { caseSensitive, end, ...linkProps } = props;
    const [routerProps, componentProps] = splitRouterLinkProps(linkProps as T);
    const stableRouterProps = useStableRouterLinkProps(routerProps);
    const RouterNavLinkSlot = React.useMemo(() => React.forwardRef<HTMLAnchorElement, SlotRootProps>(({ as: _as, disabled, href: _href, onClick, tabIndex, type: _type, value: _value, ...slotProps }, slotRef) => {
        const handleClick: React.MouseEventHandler<HTMLAnchorElement> = (event) => {
            if (mode === 'tab' && disabled) {
                event.preventDefault();
                event.stopPropagation();
                return;
            }
            onClick?.(event);
        };
        return (<RouterNavLink {...slotProps} {...stableRouterProps} target={stableRouterProps.target ?? slotProps.target} rel={stableRouterProps.rel ?? slotProps.rel} aria-disabled={mode === 'tab' && disabled ? true : undefined} caseSensitive={caseSensitive} end={end} onClick={handleClick} ref={slotRef} tabIndex={mode === 'tab' && disabled ? -1 : tabIndex}/>);
    }), [caseSensitive, end, mode, stableRouterProps]);
    return [RouterNavLinkSlot, componentProps];
}

const TabLink = React.forwardRef<HTMLAnchorElement, TabLinkProps>((props, ref) => {
    const value = typeof props.to === 'string' ? props.to : (props.to.pathname ?? '');
    const [RouterLinkSlot, tabProps] = useRouterNavLinkSlot(props, 'tab');
    return (<CoreAITab {...(tabProps as CoreAITabProps)} as={RouterLinkSlot as unknown as 'button'} ref={ref as unknown as React.Ref<HTMLButtonElement>} value={value}/>);
});

export const Default = () => (<MemoryRouter>
      <TabList selectedValue="/overview">
        <TabLink to="/overview">Overview</TabLink>
      </TabList>
    </MemoryRouter>);

export default Default;
