import * as i0 from '@angular/core';
import { Injectable } from '@angular/core';
import { Workbook } from 'exceljs';
import { SdUtilities, DateUtilities } from '@sd-angular/core/utilities/extensions';
import { mkConfig, generateCsv, download } from 'export-to-csv';

class SdExcelService {
    #fieldStyle = {
        border: {
            bottom: { style: 'thin' },
            left: { style: 'thin' },
            right: { style: 'thin' },
        },
        alignment: {
            vertical: 'middle',
            horizontal: 'center',
            wrapText: true,
        },
        font: {
            bold: true,
            size: 11,
            color: { argb: '000000' },
        },
        fill: {
            type: 'pattern',
            pattern: 'solid',
            fgColor: {
                argb: 'FAFAFA',
            },
        },
    };
    #titleColor = 'FFFFFF';
    #titleFgColor = '143180';
    #titleStyle = {
        border: {
            bottom: { style: 'thin' },
            left: { style: 'thin' },
            right: { style: 'thin' },
        },
        alignment: {
            vertical: 'middle',
            horizontal: 'center',
            wrapText: true,
        },
        font: {
            bold: true,
            size: 11,
            color: { argb: this.#titleColor },
        },
        fill: {
            type: 'pattern',
            pattern: 'solid',
            fgColor: {
                argb: this.#titleFgColor,
            },
        },
    };
    #requiredStyle = {
        border: {
            bottom: { style: 'thin' },
            left: { style: 'thin' },
            right: { style: 'thin' },
        },
        alignment: {
            vertical: 'middle',
            horizontal: 'center',
            wrapText: true,
        },
        font: {
            italic: true,
            size: 11,
            color: { argb: 'FFFFFF' },
        },
        fill: {
            type: 'pattern',
            pattern: 'solid',
            fgColor: {
                argb: 'FF1744',
            },
        },
    };
    #descriptionStyle = {
        border: {
            bottom: { style: 'thin' },
            left: { style: 'thin' },
            right: { style: 'thin' },
        },
        alignment: {
            wrapText: true,
        },
        font: {
            italic: true,
            size: 9,
            color: { argb: '000000' },
        },
        fill: {
            type: 'pattern',
            pattern: 'solid',
            fgColor: {
                argb: 'CFD8DC',
            },
        },
    };
    #cellStyle = {
        alignment: {
            vertical: 'middle',
            wrapText: true,
        },
    };
    constructor() { }
    generateTemplate = async (template) => {
        const { fileName, columns, sheets } = template;
        if (!Array.isArray(columns)) {
            throw new Error('Excel template columns must be an array');
        }
        for (const [idx, column] of columns.entries()) {
            if (!column.field) {
                throw new Error(`Column ${idx + 1}: Field is required`);
            }
            if (!column.title) {
                throw new Error(`Column ${idx + 1}: Title is required`);
            }
        }
        const hasDescription = columns.some(column => column.description);
        // const { Workbook } = await import('exceljs');
        const workbook = new Workbook();
        const firstSheet = workbook.addWorksheet('template'); // Lấy ra sheet đầu tiên
        columns.forEach((column, index) => {
            const { required, fill, fontColor } = column;
            const cellField = firstSheet.getCell(1, index + 1);
            const cellTitle = firstSheet.getCell(2, index + 1);
            const cellDescription = firstSheet.getCell(3, index + 1);
            let width = 120;
            if (column.width && column.width.endsWith('px')) {
                width = +column.width.replace('px', '');
            }
            firstSheet.getColumn(index + 1).width = width / 7 || 20;
            cellField.style = this.#fieldStyle;
            if (required) {
                cellField.style = this.#requiredStyle;
            }
            else {
                cellField.style = this.#fieldStyle;
            }
            cellTitle.style = {
                ...this.#titleStyle,
                font: {
                    ...this.#titleStyle?.font,
                    color: {
                        ...this.#titleStyle?.font?.color,
                        argb: fontColor || this.#titleStyle?.font?.color?.argb,
                    },
                },
                fill: {
                    type: 'pattern',
                    pattern: 'solid',
                    fgColor: {
                        argb: fill || this.#titleFgColor,
                    },
                },
            };
            cellField.value = column.field;
            cellTitle.value = column.title;
            if (hasDescription) {
                cellDescription.style = this.#descriptionStyle;
                cellDescription.value = column.description || '';
            }
        });
        if (sheets?.length) {
            for (const sheet of sheets) {
                if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.headers)) {
                    const newSheet = workbook.addWorksheet(sheet.name);
                    sheet.headers.forEach((header, index) => {
                        newSheet.getColumn(index + 1).width = 30;
                        newSheet.getCell(1, index + 1).style = this.#titleStyle;
                        newSheet.getCell(1, index + 1).value = header.value;
                        newSheet.getCell(2, index + 1).style = this.#titleStyle;
                        newSheet.getCell(2, index + 1).value = header.display || header.value;
                    });
                    sheet.items.forEach((item, idx1) => {
                        sheet.headers.forEach((header, idx2) => {
                            newSheet.getCell(3 + idx1, 1 + idx2).value = item[header.value];
                            newSheet.getCell(3 + idx1, 1 + idx2).style = this.#cellStyle;
                        });
                    });
                }
            }
        }
        const file = await workbook.xlsx.writeBuffer();
        SdUtilities.downloadBlob(new Blob([file], {
            type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        }), fileName);
    };
    exportCSV = async (option) => {
        const { columns, items, fileName } = option;
        const headerCSV = {};
        for (const column of columns) {
            headerCSV[column.field] = column.title;
        }
        // const { mkConfig, generateCsv, download } = await import('export-to-csv');
        const csvConfig = mkConfig({
            filename: `${fileName || 'CSV'}_${DateUtilities.toFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss')}`,
            fieldSeparator: ',',
            quoteCharacter: '"',
            decimalSeparator: '.',
            // showLabels: true,
            showTitle: false,
            title: fileName || 'CSV',
            useBom: true,
        });
        const csv = generateCsv(csvConfig)([headerCSV, ...items]); // ([headerCSV, ...items]);
        download(csvConfig)(csv);
    };
    export = async (option) => {
        const { columns, items, fileName, sheets } = option;
        let hasDescription = false;
        for (const [idx, column] of columns.entries()) {
            if (!column.field) {
                throw new Error(`Column ${idx + 1}: Field is required`);
            }
            if (!column.title) {
                throw new Error(`Column ${idx + 1}: Title is required`);
            }
            if (column.description) {
                hasDescription = true;
            }
        }
        // const { Workbook } = await import('exceljs');
        const workbook = new Workbook(); //await XlsxPopulate.fromBlankAsync(); // Đọc file sau khi đã download
        const firstSheet = workbook.addWorksheet('data'); // Lấy ra sheet đầu tiên
        columns.forEach((column, index) => {
            let width = 120;
            if (column.width && column.width.endsWith('px')) {
                width = +column.width.replace('px', '');
            }
            firstSheet.getColumn(index + 1).width = width / 7 || 20;
            firstSheet.getCell(1, index + 1).style = this.#fieldStyle;
            if (column.required) {
                firstSheet.getCell(2, index + 1).style = this.#requiredStyle;
            }
            else {
                firstSheet.getCell(2, index + 1).style = this.#titleStyle;
            }
            firstSheet.getCell(1, index + 1).value = column.field;
            firstSheet.getCell(2, index + 1).value = column.title;
            if (hasDescription) {
                firstSheet.getCell(3, index + 1).style = this.#descriptionStyle;
                firstSheet.getCell(3, index + 1).value = column.description || '';
            }
        });
        if (sheets?.length) {
            for (const sheet of sheets) {
                if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.headers)) {
                    const newSheet = workbook.addWorksheet(sheet.name);
                    sheet.headers.forEach((header, index) => {
                        newSheet.getColumn(index + 1).width = 30;
                        newSheet.getCell(1, index + 1).style = this.#titleStyle;
                        newSheet.getCell(1, index + 1).value = header.value;
                        newSheet.getCell(2, index + 1).style = this.#titleStyle;
                        newSheet.getCell(2, index + 1).value = header.display || header.value;
                    });
                    sheet.items.forEach((item, idx1) => {
                        sheet.headers.forEach((header, idx2) => {
                            newSheet.getCell(3 + idx1, 1 + idx2).value = item[header.value];
                            newSheet.getCell(3 + idx1, 1 + idx2).style = this.#cellStyle;
                        });
                    });
                }
            }
        }
        const fromRow = hasDescription ? 4 : 3;
        items.forEach((e, idx1) => {
            columns.forEach((column, idx2) => {
                if (typeof e[column.field] === 'number') {
                    // Format mặc định với kiểu số
                    firstSheet.getCell(fromRow + idx1, 1 + idx2).value = +e[column.field];
                    firstSheet.getCell(fromRow + idx1, 1 + idx2).numFmt = '#';
                }
                else {
                    firstSheet.getCell(fromRow + idx1, 1 + idx2).value = e[column.field];
                }
                firstSheet.getCell(fromRow + idx1, 1 + idx2).style = {
                    ...this.#cellStyle,
                };
            });
        });
        const file = await workbook.xlsx.writeBuffer();
        SdUtilities.downloadBlob(new Blob([file], {
            type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
        }), fileName);
    };
    // Helper để lấy giá trị text chuẩn từ ô Excel (xử lý RichText, Formula, Hyperlink)
    #getCellValue = (value) => {
        if (value && typeof value === 'object') {
            // Xử lý Rich Text (vd: ô bôi đậm)
            if ('richText' in value) {
                return value.richText.map(t => t.text).join('');
            }
            // Xử lý Hyperlink
            if ('text' in value) {
                return value.text; // hoặc value.result nếu là công thức
            }
            // Xử lý Formula
            if ('result' in value) {
                return value.result;
            }
        }
        return value;
    };
    upload = async () => {
        try {
            const fileResult = await SdUtilities.upload({
                extensions: ['xlsx'],
                maxSizeInMb: 10,
            });
            // Chuẩn hóa file đầu vào (nếu upload trả về mảng thì lấy phần tử đầu)
            const file = Array.isArray(fileResult) ? fileResult[0] : fileResult;
            if (!file) {
                return { items: [], file: null };
            }
            return await this.parse(file);
        }
        catch (error) {
            console.error('Upload error:', error);
            throw error; // Hoặc return { items: [], file: null } tùy logic nghiệp vụ
        }
    };
    parse = async (file) => {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = async (e) => {
                try {
                    const buffer = e.target?.result;
                    if (!buffer) {
                        throw new Error('Không đọc được nội dung file');
                    }
                    const wb = new Workbook();
                    await wb.xlsx.load(buffer);
                    const sheet = wb.worksheets[0];
                    if (!sheet) {
                        throw new Error('File Excel không có sheet dữ liệu');
                    }
                    const items = [];
                    // Lấy row Header (Row 1)
                    const headerRow = sheet.getRow(1);
                    // Map: Column Index (bắt đầu từ 1) -> Tên trường (Key)
                    const headerMap = {};
                    // Duyệt qua các ô có dữ liệu thực tế của dòng Header
                    headerRow.eachCell((cell, colNumber) => {
                        const cellValue = this.#getCellValue(cell.value);
                        if (cellValue) {
                            // Ép kiểu về string và trim để làm key
                            headerMap[colNumber] = String(cellValue).trim();
                        }
                    });
                    // Duyệt dữ liệu từ dòng 2 trở đi
                    sheet.eachRow((row, rowIndex) => {
                        if (rowIndex <= 1 || !row.hasValues)
                            return;
                        const item = {};
                        // Chỉ duyệt qua các cột đã định nghĩa trong headerMap
                        // Cách này an toàn hơn là duyệt mảng values
                        Object.keys(headerMap).forEach(colKey => {
                            const colNumber = Number(colKey);
                            const fieldKey = headerMap[colNumber];
                            // Lấy giá trị ô tại cột tương ứng
                            const rawValue = this.#getCellValue(row.getCell(colNumber).value);
                            let finalValue = rawValue;
                            // Xử lý string: trim
                            if (typeof finalValue === 'string') {
                                finalValue = finalValue.trim();
                            }
                            // Xử lý các keyword đặc biệt
                            if (finalValue === '' || finalValue === undefined) {
                                finalValue = null;
                            }
                            else if (finalValue === 'SET_NULL') {
                                finalValue = null;
                            }
                            else if (finalValue === 'SET_EMPTY') {
                                finalValue = '';
                            }
                            item[fieldKey] = finalValue;
                        });
                        // Chỉ push nếu item có dữ liệu (tùy chọn)
                        if (Object.keys(item).length > 0) {
                            items.push(item);
                        }
                    });
                    resolve({ items, file });
                }
                catch (err) {
                    reject(err);
                }
            };
            reader.onerror = error => reject(error);
            reader.readAsArrayBuffer(file);
        });
    };
    static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdExcelService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
    static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdExcelService, providedIn: 'root' });
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.17", ngImport: i0, type: SdExcelService, decorators: [{
            type: Injectable,
            args: [{
                    providedIn: 'root',
                }]
        }], ctorParameters: () => [] });

/**
 * Generated bundle index. Do not edit.
 */

export { SdExcelService };
//# sourceMappingURL=sd-angular-core-services-excel.mjs.map
