import inertia from '@inertiajs/vite';
import { wayfinder } from '@laravel/vite-plugin-wayfinder';
import tailwindcss from '@tailwindcss/vite';
import react from '@vitejs/plugin-react';
import laravel from 'laravel-vite-plugin';
import { bunny } from 'laravel-vite-plugin/fonts';
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { defineConfig, type Plugin } from 'vite';

/**
 * Recharts imports es-toolkit via CJS subpaths (`es-toolkit/compat/get`).
 * Rolldown resolves those to broken CJS interop in production builds.
 * Redirect to the ESM `.mjs` files instead. See recharts/recharts#7376.
 */
const esToolkitCompatFunctions: Record<string, string> = {
    get: 'object/get.mjs',
    isPlainObject: 'predicate/isPlainObject.mjs',
    last: 'array/last.mjs',
    maxBy: 'math/maxBy.mjs',
    minBy: 'math/minBy.mjs',
    omit: 'object/omit.mjs',
    range: 'math/range.mjs',
    sortBy: 'array/sortBy.mjs',
    sumBy: 'math/sumBy.mjs',
    throttle: 'function/throttle.mjs',
    uniqBy: 'array/uniqBy.mjs',
};

function esToolkitCompatEsm(): Plugin {
    const virtualPrefix = '\0es-toolkit-compat:';
    const projectRoot = path.dirname(fileURLToPath(import.meta.url));

    return {
        name: 'es-toolkit-compat-esm',
        enforce: 'pre',
        resolveId(source) {
            const prefix = 'es-toolkit/compat/';

            if (! source.startsWith(prefix)) {
                return null;
            }

            const functionName = source.slice(prefix.length);

            if (! esToolkitCompatFunctions[functionName]) {
                return null;
            }

            return `${virtualPrefix}${functionName}`;
        },
        load(id) {
            if (! id.startsWith(virtualPrefix)) {
                return null;
            }

            const functionName = id.slice(virtualPrefix.length);
            const relativePath = esToolkitCompatFunctions[functionName];

            if (! relativePath) {
                return null;
            }

            const absolutePath = path.resolve(
                projectRoot,
                'node_modules/es-toolkit/dist/compat',
                relativePath,
            );

            return [
                `import { ${functionName} } from ${JSON.stringify(absolutePath)};`,
                `export default ${functionName};`,
            ].join('\n');
        },
    };
}

export default defineConfig({
    plugins: [
        esToolkitCompatEsm(),
        laravel({
            input: ['resources/css/app.css', 'resources/js/app.tsx'],
            refresh: true,
            fonts: [
                bunny('Instrument Sans', {
                    weights: [400, 500, 600],
                }),
            ],
        }),
        inertia(),
        react({
            babel: {
                plugins: ['babel-plugin-react-compiler'],
            },
        }),
        tailwindcss(),
        wayfinder({
            formVariants: true,
        }),
    ],
    build: {
        rolldownOptions: {
            output: {
                codeSplitting: {
                    groups: [
                        {
                            name: 'vendor-recharts',
                            test: /node_modules\/(recharts|es-toolkit)\//,
                            priority: 28,
                        },
                        {
                            name: 'vendor-react',
                            test: /node_modules\/(react|react-dom|scheduler)\//,
                            priority: 30,
                        },
                        {
                            name: 'vendor-inertia',
                            test: /node_modules\/@inertiajs\//,
                            priority: 25,
                        },
                        {
                            name: 'vendor-radix',
                            test: /node_modules\/@radix-ui\//,
                            priority: 20,
                        },
                        {
                            name: 'vendor-stripe',
                            test: /node_modules\/@stripe\//,
                            priority: 20,
                        },
                        {
                            name: 'vendor',
                            test: /node_modules/,
                            maxSize: 500_000,
                            priority: 10,
                        },
                    ],
                },
            },
        },
    },
});
