import fs from 'fs/promises';
import path from 'path';
import mimeTypes from 'mime-types';
export class OnePageConverter {
    constructor(projectDir, options) {
        this.assets = [];
        this.projectDir = projectDir;
        this.options = options;
    }
    /**
     * 添加资产到转换列表
     */
    addAsset(assetPath, type) {
        this.assets.push({
            path: assetPath,
            type,
            size: 0,
        });
    }
    /**
     * 编码所有资产为 Base64
     */
    async encodeAssets() {
        for (const asset of this.assets) {
            const fullPath = path.join(this.projectDir, asset.path);
            try {
                const fileBuffer = await fs.readFile(fullPath);
                asset.size = fileBuffer.length;
                asset.base64 = fileBuffer.toString('base64');
                asset.mimeType = mimeTypes.lookup(asset.path) || 'application/octet-stream';
            }
            catch (error) {
                console.warn(`Warning: Failed to encode asset ${asset.path}: ${error.message}`);
            }
        }
    }
    /**
     * 获取资产的 Base64 数据 URL
     */
    getDataUrl(assetPath) {
        if (!assetPath)
            return null;
        // 移除查询参数
        let cleanPath = assetPath;
        if (cleanPath.includes('?')) {
            cleanPath = cleanPath.split('?')[0];
        }
        // 解码 URL 编码的路径
        try {
            cleanPath = decodeURIComponent(cleanPath);
        }
        catch (e) {
            // 如果解码失败，使用原始路径
        }
        // 1. 精确匹配
        let asset = this.assets.find(a => a.path === cleanPath);
        // 2. 尝试移除前导斜杠
        if (!asset && cleanPath.startsWith('/')) {
            asset = this.assets.find(a => a.path === cleanPath.substring(1));
        }
        // 3. 尝试模糊匹配（文件名匹配）
        if (!asset) {
            const filename = path.basename(cleanPath);
            asset = this.assets.find(a => {
                const assetFilename = path.basename(a.path);
                return assetFilename === filename;
            });
        }
        // 4. 尝试部分路径匹配（处理 files/assets/... 格式）
        if (!asset) {
            asset = this.assets.find(a => a.path.endsWith(cleanPath) || cleanPath.endsWith(a.path));
        }
        if (!asset || !asset.base64) {
            return null;
        }
        return `data:${asset.mimeType};base64,${asset.base64}`;
    }
    /**
     * 替换 HTML 中的 URL 为 Base64 数据 URL
     */
    replaceUrlsWithBase64(html, urlMap) {
        let result = html;
        for (const [url, dataUrl] of urlMap.entries()) {
            // 替换各种可能的 URL 格式
            result = result.replace(new RegExp(url.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), dataUrl);
            // 也替换相对路径
            const relativeUrl = url.startsWith('/') ? url.substring(1) : url;
            result = result.replace(new RegExp(relativeUrl.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g'), dataUrl);
        }
        return result;
    }
    /**
     * 内联脚本到 HTML
     */
    async inlineScripts(html) {
        // 查找所有 <script src="..."> 标签
        const scriptRegex = /<script\s+src=["']([^"']+)["'][^>]*><\/script>/gi;
        let result = html;
        const matches = [];
        let match;
        // 先收集所有匹配项
        while ((match = scriptRegex.exec(html)) !== null) {
            matches.push({
                fullMatch: match[0],
                scriptPath: match[1],
            });
        }
        // 处理每个脚本
        for (const { fullMatch, scriptPath } of matches) {
            // 尝试多个可能的路径
            const possiblePaths = [
                path.join(this.projectDir, scriptPath),
                path.join(this.projectDir, scriptPath.replace(/^\//, '')),
                scriptPath, // 绝对路径
            ];
            let scriptContent = null;
            for (const fullPath of possiblePaths) {
                try {
                    scriptContent = await fs.readFile(fullPath, 'utf-8');
                    break;
                }
                catch (error) {
                    // 继续尝试下一个路径
                }
            }
            if (scriptContent) {
                // 替换为内联脚本
                result = result.replace(fullMatch, `<script>${scriptContent}</script>`);
            }
            else {
                console.warn(`Warning: Failed to inline script ${scriptPath}`);
            }
        }
        return result;
    }
    /**
     * 获取所有资产信息
     */
    getAssets() {
        return this.assets;
    }
    /**
     * 获取总大小
     */
    getTotalSize() {
        return this.assets.reduce((sum, asset) => sum + asset.size, 0);
    }
}
