import { existsSync, mkdirSync, statSync, truncateSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { getMidsceneRunSubDir } from "@midscene/shared/common";
import { MIDSCENE_REPORT_QUIET, globalConfigManager } from "@midscene/shared/env";
import { ifInBrowser, logMsg } from "@midscene/shared/utils";
import { BASE_URL_FIX_SCRIPT, generateDumpScriptTag, generateImageScriptTag } from "./dump/html-utils.mjs";
import { appendFileSync, getReportTpl } from "./utils.mjs";
function _define_property(obj, key, value) {
    if (key in obj) Object.defineProperty(obj, key, {
        value: value,
        enumerable: true,
        configurable: true,
        writable: true
    });
    else obj[key] = value;
    return obj;
}
const nullReportGenerator = {
    onDumpUpdate: ()=>{},
    flush: async ()=>{},
    finalize: async ()=>void 0,
    getReportPath: ()=>void 0
};
class ReportGenerator {
    static create(reportFileName, opts) {
        if (false === opts.generateReport) return nullReportGenerator;
        if (ifInBrowser) return nullReportGenerator;
        if ('html-and-external-assets' === opts.outputFormat) {
            const outputDir = join(getMidsceneRunSubDir('report'), reportFileName);
            return new ReportGenerator({
                reportPath: join(outputDir, 'index.html'),
                screenshotMode: 'directory',
                autoPrint: opts.autoPrintReportMsg
            });
        }
        return new ReportGenerator({
            reportPath: join(getMidsceneRunSubDir('report'), `${reportFileName}.html`),
            screenshotMode: 'inline',
            autoPrint: opts.autoPrintReportMsg
        });
    }
    onDumpUpdate(dump) {
        this.writeQueue = this.writeQueue.then(()=>{
            if (this.destroyed) return;
            this.doWrite(dump);
        });
    }
    async flush() {
        await this.writeQueue;
    }
    async finalize(dump) {
        this.onDumpUpdate(dump);
        await this.flush();
        this.destroyed = true;
        this.printReportPath('finalized');
        return this.reportPath;
    }
    getReportPath() {
        return this.reportPath;
    }
    printReportPath(verb) {
        if (!this.autoPrint || !this.reportPath) return;
        if (globalConfigManager.getEnvConfigInBoolean(MIDSCENE_REPORT_QUIET)) return;
        'directory' === this.screenshotMode ? logMsg(`Midscene - report ${verb}: npx serve ${dirname(this.reportPath)}`) : logMsg(`Midscene - report ${verb}: ${this.reportPath}`);
    }
    doWrite(dump) {
        if ('inline' === this.screenshotMode) this.writeInlineReport(dump);
        else this.writeDirectoryReport(dump);
        if (!this.firstWriteDone) {
            this.firstWriteDone = true;
            this.printReportPath('generated');
        }
    }
    writeInlineReport(dump) {
        const dir = dirname(this.reportPath);
        if (!existsSync(dir)) mkdirSync(dir, {
            recursive: true
        });
        if (!this.initialized) {
            writeFileSync(this.reportPath, getReportTpl());
            this.imageEndOffset = statSync(this.reportPath).size;
            this.initialized = true;
        }
        truncateSync(this.reportPath, this.imageEndOffset);
        const screenshots = dump.collectAllScreenshots();
        for (const screenshot of screenshots)if (!this.writtenScreenshots.has(screenshot.id)) {
            appendFileSync(this.reportPath, `\n${generateImageScriptTag(screenshot.id, screenshot.base64)}`);
            this.writtenScreenshots.add(screenshot.id);
            screenshot.markPersistedInline(this.reportPath);
        }
        this.imageEndOffset = statSync(this.reportPath).size;
        const serialized = dump.serialize();
        appendFileSync(this.reportPath, `\n${generateDumpScriptTag(serialized)}`);
    }
    writeDirectoryReport(dump) {
        const dir = dirname(this.reportPath);
        if (!existsSync(dir)) mkdirSync(dir, {
            recursive: true
        });
        const screenshotsDir = join(dir, 'screenshots');
        if (!existsSync(screenshotsDir)) mkdirSync(screenshotsDir, {
            recursive: true
        });
        const screenshots = dump.collectAllScreenshots();
        for (const screenshot of screenshots)if (!this.writtenScreenshots.has(screenshot.id)) {
            const ext = screenshot.extension;
            const absolutePath = join(screenshotsDir, `${screenshot.id}.${ext}`);
            const buffer = Buffer.from(screenshot.rawBase64, 'base64');
            writeFileSync(absolutePath, buffer);
            this.writtenScreenshots.add(screenshot.id);
            screenshot.markPersistedToPath(`./screenshots/${screenshot.id}.${ext}`, absolutePath);
        }
        const serialized = dump.serialize();
        writeFileSync(this.reportPath, `${getReportTpl()}${BASE_URL_FIX_SCRIPT}${generateDumpScriptTag(serialized)}`);
    }
    constructor(options){
        _define_property(this, "reportPath", void 0);
        _define_property(this, "screenshotMode", void 0);
        _define_property(this, "autoPrint", void 0);
        _define_property(this, "writtenScreenshots", new Set());
        _define_property(this, "firstWriteDone", false);
        _define_property(this, "imageEndOffset", 0);
        _define_property(this, "initialized", false);
        _define_property(this, "writeQueue", Promise.resolve());
        _define_property(this, "destroyed", false);
        this.reportPath = options.reportPath;
        this.screenshotMode = options.screenshotMode;
        this.autoPrint = options.autoPrint ?? true;
        this.printReportPath('will be generated at');
    }
}
export { ReportGenerator, nullReportGenerator };

//# sourceMappingURL=report-generator.mjs.map