import { copyFileSync, existsSync, mkdirSync, statSync, writeFileSync } from "node:fs";
import { basename, dirname, extname, join, resolve } from "node:path";
import { z } from "zod";
import { resolveScreenshotSource } from "./dump/screenshot-store.mjs";
import { ReportMergingTool, collectDedupedExecutions, splitReportHtmlByExecution } from "./report.mjs";
import { reportToMarkdown } from "./report-markdown.mjs";
import { ReportActionDump } from "./types.mjs";
function writeAttachmentFromReport(attachment, opts) {
    const { suggestedFileName, id, mimeType } = attachment;
    if (opts.writtenFiles.has(suggestedFileName)) return;
    const absolutePath = join(opts.screenshotsDir, suggestedFileName);
    const resolved = resolveScreenshotSource(attachment.sourceRef ?? null, {
        reportPath: opts.htmlPath,
        fallbackId: id,
        fallbackMimeType: mimeType || 'image/png'
    });
    if ('data-uri' === resolved.type) {
        const rawBase64 = resolved.dataUri.replace(/^data:image\/[a-zA-Z+]+;base64,/, '');
        writeFileSync(absolutePath, Buffer.from(rawBase64, 'base64'));
        opts.writtenFiles.add(suggestedFileName);
        return;
    }
    if (!existsSync(resolved.filePath)) throw new Error(`Cannot resolve screenshot "${id}" for markdown attachment from ${opts.htmlPath}`);
    copyFileSync(resolved.filePath, absolutePath);
    opts.writtenFiles.add(suggestedFileName);
}
async function markdownFromReport(htmlPath, outputDir) {
    const screenshotsDir = join(outputDir, 'screenshots');
    mkdirSync(outputDir, {
        recursive: true
    });
    mkdirSync(screenshotsDir, {
        recursive: true
    });
    const { baseDump, executions } = collectDedupedExecutions(htmlPath);
    const mergedReport = new ReportActionDump({
        sdkVersion: baseDump.sdkVersion,
        groupName: baseDump.groupName,
        groupDescription: baseDump.groupDescription,
        modelBriefs: baseDump.modelBriefs,
        deviceType: baseDump.deviceType,
        executions
    });
    const result = reportToMarkdown(mergedReport);
    const markdownFiles = [];
    const writtenScreenshots = new Set();
    const mdPath = join(outputDir, 'report.md');
    writeFileSync(mdPath, result.markdown, 'utf-8');
    markdownFiles.push(mdPath);
    for (const attachment of result.attachments)writeAttachmentFromReport(attachment, {
        htmlPath,
        screenshotsDir,
        writtenFiles: writtenScreenshots
    });
    return {
        markdownFiles,
        screenshotFiles: Array.from(writtenScreenshots).sort().map((f)=>join(screenshotsDir, f))
    };
}
function resolveReportHtmlPath(htmlPath) {
    const normalizedPath = resolve(htmlPath);
    if (!existsSync(normalizedPath)) throw new Error(`report-tool: --htmlPath does not exist: ${htmlPath}`);
    const stats = statSync(normalizedPath);
    if (!stats.isDirectory()) return normalizedPath;
    const indexHtmlPath = join(normalizedPath, 'index.html');
    if (!existsSync(indexHtmlPath)) throw new Error(`report-tool: "${htmlPath}" is not an HTML report file, and no index.html was found under this directory.`);
    return indexHtmlPath;
}
function splitReportFile(options) {
    const { htmlPath, outputDir } = options;
    if (!htmlPath) throw new Error('splitReportFile: htmlPath is required');
    if (!outputDir) throw new Error('splitReportFile: outputDir is required');
    const resolvedHtmlPath = resolveReportHtmlPath(htmlPath);
    return splitReportHtmlByExecution({
        htmlPath: resolvedHtmlPath,
        outputDir
    });
}
async function reportFileToMarkdown(options) {
    const { htmlPath, outputDir } = options;
    if (!htmlPath) throw new Error('reportFileToMarkdown: htmlPath is required');
    if (!outputDir) throw new Error('reportFileToMarkdown: outputDir is required');
    const resolvedHtmlPath = resolveReportHtmlPath(htmlPath);
    return markdownFromReport(resolvedHtmlPath, outputDir);
}
function deriveReportAttributesFromHtml(htmlPath, index) {
    const fallbackId = `${basename(dirname(htmlPath)) || basename(htmlPath, extname(htmlPath))}-${index + 1}`;
    try {
        const { baseDump } = collectDedupedExecutions(htmlPath);
        return {
            testId: fallbackId,
            testTitle: baseDump.groupName || fallbackId,
            testDescription: baseDump.groupDescription ?? '',
            testDuration: 0,
            testStatus: 'passed'
        };
    } catch  {
        return {
            testId: fallbackId,
            testTitle: fallbackId,
            testDescription: '',
            testDuration: 0,
            testStatus: 'passed'
        };
    }
}
function mergeReportFiles(options) {
    const { htmlPaths, outputDir, outputName, overwrite = false } = options;
    if (!htmlPaths || 0 === htmlPaths.length) throw new Error('mergeReportFiles: htmlPaths is required');
    const resolvedPaths = htmlPaths.map((p)=>resolveReportHtmlPath(p));
    const tool = new ReportMergingTool();
    resolvedPaths.forEach((htmlPath, index)=>{
        tool.append({
            reportFilePath: htmlPath,
            reportAttributes: deriveReportAttributesFromHtml(htmlPath, index)
        });
    });
    const mergedReportPath = tool.mergeReports(outputName ?? 'AUTO', {
        overwrite,
        outputDir
    });
    if (!mergedReportPath) throw new Error('mergeReportFiles: failed to produce a merged report');
    return {
        mergedReportPath
    };
}
function normalizeHtmlReportArg(raw) {
    if (null == raw) return;
    if (Array.isArray(raw)) return raw.filter((p)=>'string' == typeof p && p.length > 0);
    if ('string' == typeof raw) {
        const trimmed = raw.trim();
        return trimmed ? [
            trimmed
        ] : [];
    }
}
const reportCommandDefinition = {
    name: 'report-tool',
    description: 'Transform Midscene report artifacts, including splitting executions, converting to markdown, and merging multiple reports.',
    schema: {
        action: z["enum"]([
            'split',
            'to-markdown',
            'merge-html'
        ]).optional().describe('Report action to run. Supports: split, to-markdown, merge-html. Defaults to split.'),
        htmlPath: z.string().optional().describe('Input report HTML path (e.g. ./report/index.html). Used by split and to-markdown.'),
        htmlReport: z.union([
            z.string(),
            z.array(z.string())
        ]).optional().describe('Input report HTML path for the merge action. Repeat the flag to merge multiple reports (e.g. --htmlReport ./a/index.html --htmlReport ./b.html).'),
        outputDir: z.string().optional().describe('Output directory for generated report artifacts. For merge, defaults to the Midscene report directory.'),
        outputName: z.string().optional().describe('Output report file/directory name (without .html) for the merge action. Defaults to an auto-generated name.'),
        overwrite: z.union([
            z.boolean(),
            z.string()
        ]).optional().describe('Overwrite the existing merged report file if present (merge action only).')
    },
    handler: async (args)=>{
        const { action = 'split', htmlPath, htmlReport, outputDir, outputName, overwrite } = args;
        if ('split' !== action && 'to-markdown' !== action && 'merge-html' !== action) throw new Error(`report-tool: unsupported --action value "${action}". Currently supported: split, to-markdown, merge-html`);
        if ('merge-html' === action) {
            const paths = normalizeHtmlReportArg(htmlReport);
            if (!paths || 0 === paths.length) throw new Error('report-tool: --htmlReport is required for action "merge-html". Repeat --htmlReport for each report (e.g. --htmlReport ./a/index.html --htmlReport ./b.html).');
            const overwriteFlag = true === overwrite || 'true' === overwrite || '1' === overwrite;
            const result = mergeReportFiles({
                htmlPaths: paths,
                outputDir,
                outputName,
                overwrite: overwriteFlag
            });
            return {
                isError: false,
                content: [
                    {
                        type: 'text',
                        text: `Merged ${paths.length} report(s) into ${result.mergedReportPath}`
                    }
                ]
            };
        }
        if (!htmlPath) throw new Error('report-tool: --htmlPath is required');
        if (!outputDir) throw new Error('report-tool: --outputDir is required');
        if ('to-markdown' === action) {
            const result = await reportFileToMarkdown({
                htmlPath,
                outputDir
            });
            return {
                isError: false,
                content: [
                    {
                        type: 'text',
                        text: `Markdown export completed. Generated ${result.markdownFiles.length} markdown file(s) and ${result.screenshotFiles.length} screenshot(s). Output path: ${outputDir}`
                    }
                ]
            };
        }
        const result = splitReportFile({
            htmlPath,
            outputDir
        });
        return {
            isError: false,
            content: [
                {
                    type: 'text',
                    text: `Report split completed. Generated ${result.executionJsonFiles.length} execution JSON files and ${result.screenshotFiles.length} screenshots. Output path: ${outputDir}`
                }
            ]
        };
    }
};
function createReportCliCommands() {
    return [
        {
            name: 'report-tool',
            def: reportCommandDefinition
        }
    ];
}
export { createReportCliCommands, mergeReportFiles, reportFileToMarkdown, splitReportFile };

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