import { existsSync, mkdirSync, 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, uuid } from "@midscene/shared/utils";
import { generateDumpScriptTag, generateImageScriptTag, getBaseUrlFixScript } from "./dump/html-utils.mjs";
import { GroupedActionDump } from "./types.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 = {
    onExecutionUpdate: ()=>{},
    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
        });
    }
    onExecutionUpdate(execution, groupMeta) {
        this.lastExecution = execution;
        this.lastGroupMeta = groupMeta;
        this.writeQueue = this.writeQueue.then(()=>{
            if (this.destroyed) return;
            this.doWriteExecution(execution, groupMeta);
        });
    }
    async flush() {
        await this.writeQueue;
    }
    async finalize() {
        if (this.lastExecution && this.lastGroupMeta) this.onExecutionUpdate(this.lastExecution, this.lastGroupMeta);
        await this.flush();
        this.destroyed = true;
        if (!this.initialized) return;
        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}`);
    }
    doWriteExecution(execution, groupMeta) {
        if ('inline' === this.screenshotMode) this.writeInlineExecution(execution, groupMeta);
        else this.writeDirectoryExecution(execution, groupMeta);
        if (!this.firstWriteDone) {
            this.firstWriteDone = true;
            this.printReportPath('generated');
        }
    }
    wrapAsGroupedDump(execution, groupMeta) {
        return new GroupedActionDump({
            sdkVersion: groupMeta.sdkVersion,
            groupName: groupMeta.groupName,
            groupDescription: groupMeta.groupDescription,
            modelBriefs: groupMeta.modelBriefs,
            deviceType: groupMeta.deviceType,
            executions: [
                execution
            ]
        });
    }
    writeInlineExecution(execution, groupMeta) {
        const dir = dirname(this.reportPath);
        if (!existsSync(dir)) mkdirSync(dir, {
            recursive: true
        });
        if (!this.initialized) {
            writeFileSync(this.reportPath, getReportTpl());
            this.initialized = true;
        }
        const screenshots = execution.collectScreenshots();
        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);
        }
        const singleDump = this.wrapAsGroupedDump(execution, groupMeta);
        const serialized = singleDump.serialize();
        const attributes = {
            'data-group-id': this.reportStreamId
        };
        appendFileSync(this.reportPath, `\n${generateDumpScriptTag(serialized, attributes)}`);
    }
    writeDirectoryExecution(execution, groupMeta) {
        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 = execution.collectScreenshots();
        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 singleDump = this.wrapAsGroupedDump(execution, groupMeta);
        const serialized = singleDump.serialize();
        const dumpAttributes = {
            'data-group-id': this.reportStreamId
        };
        if (!this.initialized) {
            writeFileSync(this.reportPath, `${getReportTpl()}${getBaseUrlFixScript()}`);
            this.initialized = true;
        }
        appendFileSync(this.reportPath, `\n${generateDumpScriptTag(serialized, dumpAttributes)}`);
    }
    constructor(options){
        _define_property(this, "reportPath", void 0);
        _define_property(this, "screenshotMode", void 0);
        _define_property(this, "autoPrint", void 0);
        _define_property(this, "firstWriteDone", false);
        _define_property(this, "reportStreamId", void 0);
        _define_property(this, "writtenScreenshots", new Set());
        _define_property(this, "initialized", false);
        _define_property(this, "lastExecution", void 0);
        _define_property(this, "lastGroupMeta", void 0);
        _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.reportStreamId = uuid();
        this.printReportPath('will be generated at');
    }
}
export { ReportGenerator, nullReportGenerator };

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