import { ResultItem, ParserResultBeforeHookArgs } from '@pandacss/types';
import { TransformResult } from 'unplugin';
import { PandaContext } from '@pandacss/node';
import { SourceFile } from 'ts-morph';

type OptimizeJsType = 'auto' | 'macro';
type Pretty<T> = {
    [K in keyof T]: T[K];
} & {};
type ResultType = NonNullable<ResultItem['type']>;
type OptimizeJsMap = Pretty<Partial<Record<Exclude<ResultType, 'sva' | 'jsx' | 'jsx-recipe'>, OptimizeJsType>>>;
type OptimizeJsOption = OptimizeJsType | OptimizeJsMap;
interface TransformOptions {
    /**
     * Will transform your source code to inline the `css` / `cva` / `${patternFn}` resulting classNames or even simplify `styled` JSX factory to their primitive HTML tags
     *
     * If set to "macro" -> will only transform imports marked as `with { type: "macro" }`
     * @example
     * ```ts
     * import { css } from '../styled-system/css' with { type: "macro" }
     *
     * const className = css({ display: "flex", flexDirection: "column", color: "red.300" })
     * // -> `const className = 'd_flex flex_column text_red.300'`
     * ```
     */
    optimizeJs?: OptimizeJsOption;
}

interface PandaPluginOptions extends Partial<PandaPluginHooks>, Pick<TransformOptions, 'optimizeJs'> {
    /** @see https://panda-css.com/docs/references/config#cwd */
    cwd?: string;
    /** @see https://panda-css.com/docs/references/cli#--config--c-1 */
    configPath?: string | undefined;
    /**
     * If set, output the generated CSS to the filesystem instead of the virtual module (`virtual:panda.css`).
     * @see https://panda-css.com/docs/references/cli#--outfile
     */
    outfile?: string | undefined;
    /**
     * @see https://www.npmjs.com/package/@rollup/pluginutils#include-and-exclude
     * @default `[/\.[cm]?[jt]sx?$/]`
     */
    include?: string | RegExp | (string | RegExp)[];
    /**
     * @see https://www.npmjs.com/package/@rollup/pluginutils#include-and-exclude
     * @default [/node_modules/]
     */
    exclude?: string | RegExp | (string | RegExp)[];
    /**
     * Will remove unused CSS variables and keyframes from the generated CSS
     */
    optimizeCss?: boolean;
    /**
     * Perform CSS minification
     *
     * @default false
     */
    minifyCss?: boolean;
    /**
     * Generate a styled-system folder on server start.
     *
     * @default true
     * @deprecated Use 'codegen' instead
     */
    codeGen?: boolean;
    /**
     * Generate a styled-system folder on server start.
     *
     * @default true
     */
    codegen?: boolean;
}
interface SourceFileHookArgs {
    sourceFile: SourceFile;
    context: PandaContext;
}
type MaybePromise<T> = T | Promise<T>;
interface PandaPluginHooks {
    contextCreated: (args: {
        context: PandaContext;
    }) => MaybePromise<void>;
    /**
     * A transform callback similar to the `transform` hook of `vite` that allows you to modify the source code before it's parsed.
     * Called before the source file is parsed by ts-morph and Panda.
     */
    transform: (args: Omit<ParserResultBeforeHookArgs, 'configure'> & Pick<SourceFileHookArgs, 'context'>) => MaybePromise<TransformResult | void>;
    /**
     * A callback that allows you to modify or use the ts-morph sourceFile before it's parsed by Panda.
     * Called after ts-morph has parsed the source file, but before it was parsed by Panda.
     */
    onSourceFile: (args: SourceFileHookArgs) => MaybePromise<void>;
}

export type { PandaPluginOptions as P };
