import {Plugin, InputPluginOption, RollupOptions, OutputOptions, RollupOutput} from "rollup";
import {TestOptions as BrowserTestOptions, TestOutput as PuppeteerTestOutput} from "./puppeteer-run-test.js";
import { rollup } from "rollup";
import serveTest, {LogCallback} from "./serve-test.ts";
import type {ExecutionContext} from "ava";
import {getCode, TestOutput} from "./code-output.ts";

export interface OutputFilterOptions {
    html?: boolean
    console?: ('log'|'error'|'warn')[] | true
    errors?: boolean, // again don't know possible values
    responses?: boolean, // interesting to see what other values were requested
    requestsFailed?: boolean, // will probably also be replicated into console errors, but helpful to have if imports werent found
}
export interface BrowserTestInput extends BrowserTestOptions{
    log?: LogCallback;
    /**
     * Optionally specify what to filter from the output
     */
    filterOutput?: OutputFilterOptions;
}


export interface BrowserTestOutput extends PuppeteerTestOutput{
    code: TestOutput[];
}

export  async function runBrowserTest(
    build: RollupOptions,
    test?: BrowserTestInput | false,
    output?: OutputOptions
) : Promise<Partial<BrowserTestOutput>>{
    const resolvedPlugins = await Promise.resolve(build.plugins||null);
    let pluginsArray : InputPluginOption[] = [];
    if(resolvedPlugins && resolvedPlugins instanceof Array){
        pluginsArray = resolvedPlugins
    }else if(resolvedPlugins){
        pluginsArray = [resolvedPlugins];
    }

    let testOutput: Partial<BrowserTestOutput> = {};
    const bundle = await rollup({
      ...build,
        plugins: [
            ...pluginsArray,
            // TODO check if browser output is requested (either for snapshot or for testing)
            ...(test? [serveTest({
                // TODO: intercept output from the serveTest? (and include as one bit in output options below, for snapshotting)
                ...test,
                log: test.log ?? console.log,
                onResult: (output)=>{
                    testOutput = {...testOutput, ...output};
                }
            })]: [])
        ]
    });

    // TODO make configurable?
    const generated = await bundle.generate({
        dir: 'output', // Output all files
        format: 'es', //  iifi and cjs should be added to tests
        sourcemap: true,// Test if #sourcemapUrl is not accidentally included in the html-output
        chunkFileNames: '[name].js',
        entryFileNames: '[name].mjs',
        assetFileNames: '[name].[extname]',
    });

    if(output){
        testOutput.code = await getCode(bundle, output);
    }
    await bundle.close();

    return testOutput

}
