export type Action<T extends string = string, TPayload = unknown> = {
    type: T;
    meta?: Record<string, unknown>;
} & {
    payload?: TPayload;
};

export type ActionGenerator<
    TType extends string = string,
    TPayloadGen = undefined
> = {
    type: TType;
} & (TPayloadGen extends (...args: any) => any
    ? (...args: Parameters<TPayloadGen>) => {
          type: TType;
          payload: ReturnType<TPayloadGen>;
      }
    : (...args: any[]) => { type: TType; payload?: unknown });

// interface Action {
//     <T extends string = string>(actionType: T): ActionGenerator<T>;
//     <T extends string = string, F extends Function = Function>(
//         actionType: T,
//         payloadGen: F
//     ): ActionGenerator<T, F>;
// }

export function action(type, payloadFunction = null) {
    const generator = function (...payloadArg) {
        const result: Action = { type };

        if (payloadFunction) {
            result.payload = payloadFunction(...payloadArg);
        } else {
            if (payloadArg[0] !== undefined) result.payload = payloadArg[0];
        }

        return result;
    };

    generator.type = type;

    return generator;
}
