import * as React from 'react';

// export type EvokitProps<P extends Record<string, string | number>> = {
//     [K in keyof P]: P[K] | `${P[K]}` | P[K][] | `${P[K]}`[] | Partial<Record<`${P[K]}`, boolean>>;
// };
// type PolymorphicRef<T extends React.ElementType> = React.ComponentPropsWithRef<T>['ref'];
// type PropsToOmit<T extends React.ElementType, N extends string, P> = keyof (AsProp<T, N> & P);
// Omit<React.ComponentPropsWithoutRef<T>, keyof (P & BaseProps<T, N>)> &

type EvokitPreset = {
    b?: string;
    m?: string;
    v?: string;
    css?: Record<string, string>;
};

type EvokitMedia = 'small' | 'medium' | 'large' | 'wide' | 'huge';

type PropsPrefix<P extends string, T> = {
    [Property in keyof T as `${P}-${string & Property}`]?: T[Property];
};

type BaseProps<T extends React.ElementType, N extends string> = PropsPrefix<
    N,
    {
        as?: T;
        preset?: EvokitPreset;
    }
>;

type PolymorphicComponentProp<
    T extends React.ElementType,
    N extends string,
    P = {}
> = React.ComponentPropsWithoutRef<T> & React.PropsWithChildren<P & BaseProps<T, N>>;

type PolymorphicComponentPropWithRef<T extends React.ElementType, N extends string, P = {}> = PolymorphicComponentProp<
    T,
    N,
    P
> & {
    ref?: React.ComponentPropsWithRef<T>['ref'];
};

export type EvokitMediaSufix<T extends string | number> = T | `${T}` | `${T}@${EvokitMedia}`;

export type EvokitProp<T extends string | number> = T | `${T}` | T[] | `${T}`[] | Partial<Record<`${T}`, boolean>>;

export interface CreateBlock<E extends React.ElementType, N extends string, P = {}> {
    <T extends React.ElementType = E>(props: PolymorphicComponentPropWithRef<T, N, P>): React.ReactNode;
    propTypes?: React.WeakValidationMap<PolymorphicComponentProp<E, N, P>> | undefined;
    contextTypes?: React.ValidationMap<any> | undefined;
    defaultProps?: Partial<PolymorphicComponentProp<E, N, P>> | undefined;
    displayName?: string | undefined;
}
