/**
 * DataExtractor.ts
 * 该文件定义了数据提取器类，用于从 Excel 文件中提取数据。
 */

import { join } from 'path';
import { readdirSync, readFileSync } from 'fs';
import * as XLSX from 'xlsx';

/**
 * 该文件定义了数据提取器类，采用单例模式，用于加载和解析 Excel 文件中的数据。
 */
export class DataExtractor {
    private static instance: DataExtractor;
    private data: { [key: string]: { [sheet: string]: any } } = {};

    /**
     * 私有构造函数，防止外部实例化，加载所有数据。
     */
    private constructor() {
        this.loadAllData();
    }

    /**
     * 获取 DataExtractor 类的实例，确保单例模式。
     * @returns DataExtractor 的实例。
     */
    public static getInstance(): DataExtractor {
        if (!DataExtractor.instance) {
            DataExtractor.instance = new DataExtractor();
        }
        return DataExtractor.instance;
    }

    /**
     * 加载目录中所有 Excel 文件的数据。
     */
    private loadAllData(): void {
        const dirPath = join(__dirname, '../../src/data');
        const files = readdirSync(dirPath).filter(file => file.endsWith('.xlsx'));

        files.forEach(file => {
            const filePath = join(dirPath, file);
            this.data[file] = this.parseExcel(filePath);
        });
    }

    /**
     * 解析 Excel 文件，将其转换为 JSON 格式。
     * @param filePath - Excel 文件的路径。
     * @returns 解析后的数据，以工作表名称为键的对象。
     */
    private parseExcel(filePath: string): { [sheet: string]: any } {
        const file = readFileSync(filePath);
        const workbook = XLSX.read(file, { type: 'buffer' });
        const sheetNames = workbook.SheetNames;
        const data: { [sheet: string]: any } = {};

        sheetNames.forEach(sheetName => {
            data[sheetName] = XLSX.utils.sheet_to_json(workbook.Sheets[sheetName]);
        });

        return data;
    }

    /**
     * 获取指定文件和工作表中的数据。
     * @param fileName - 文件名称。
     * @param sheetName - 工作表名称。
     * @returns 指定工作表中的数据。
     * @throws 如果文件或工作表不存在，则抛出错误。
     */
    public getData(fileName: string, sheetName: string): any {
        const fileData = this.data[fileName];
        if (!fileData) {
            throw new Error(`Excel文件不存在`);
        }
        const sheetData = fileData[sheetName];
        if (!sheetData) {
            throw new Error(`表格不存在`);
        }
        return sheetData;
    }
}
