import { FIREBASE_CONFIG } from '@sd-angular/core/common';
import { __classPrivateFieldGet, __awaiter } from 'tslib';
import { ɵɵdefineInjectable, ɵɵinject, Injectable, Inject, Optional } from '@angular/core';
import { SdApiService } from '@sd-angular/core/api';
import { v4 } from 'uuid';
import hash from 'object-hash';
import { ExportToCsv } from 'export-to-csv';
import { Workbook } from 'exceljs';
import { SdNotifyService } from '@sd-angular/core/notify';

const API = {
    uploadTemplate: '/excel/uploadTemplate',
    generateUploadTemplate: '/excel/generateUploadTemplate',
    filesInFolder: '/excel/filesInFolder',
    removeFile: '/excel/remove',
    sdExportByTemplate: '/excel/sd-export-by-template',
    sdMergePDF: '/excel/sd-merge-pdf',
};

var _fieldStyle, _titleColor, _titleFgColor, _titleStyle, _requiredStyle, _descriptionStyle, _cellStyle, _directory;
class SdExportService {
    constructor(apiService, notifyService, firebaseConfiguration) {
        this.apiService = apiService;
        this.notifyService = notifyService;
        this.firebaseConfiguration = firebaseConfiguration;
        _fieldStyle.set(this, {
            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.set(this, 'FFFFFF');
        _titleFgColor.set(this, '143180');
        _titleStyle.set(this, {
            border: {
                bottom: { style: 'thin' },
                left: { style: 'thin' },
                right: { style: 'thin' },
            },
            alignment: {
                vertical: 'middle',
                horizontal: 'center',
                wrapText: true,
            },
            font: {
                bold: true,
                size: 11,
                color: { argb: __classPrivateFieldGet(this, _titleColor) },
            },
            fill: {
                type: 'pattern',
                pattern: 'solid',
                fgColor: {
                    argb: __classPrivateFieldGet(this, _titleFgColor),
                },
            },
        });
        _requiredStyle.set(this, {
            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.set(this, {
            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.set(this, {
            alignment: {
                vertical: 'middle',
                wrapText: true,
            },
        });
        _directory.set(this, (key, group) => {
            let hashedFolder = hash({
                folder: this.folder,
                userFolder: this.userFolder,
            });
            if (!group) {
                return `dir1=${this.folder}&dir2=U-${hashedFolder}&dir3=${key || ''}`;
            }
            hashedFolder = hash({
                folder: this.folder,
                group,
            });
            return `dir1=${this.folder}&dir2=G-${hashedFolder}&dir3=${key || ''}`;
        });
        this.generateTemplate = (template) => __awaiter(this, void 0, void 0, function* () {
            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 = new Workbook(); //await XlsxPopulate.fromBlankAsync(); // Đọc file sau khi đã download
            const firstSheet = workbook.addWorksheet('template'); // Lấy ra sheet đầu tiên
            columns.forEach((column, index) => {
                var _a, _b, _c, _d, _e, _f;
                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 = __classPrivateFieldGet(this, _fieldStyle);
                if (required) {
                    cellField.style = __classPrivateFieldGet(this, _requiredStyle);
                }
                else {
                    cellField.style = __classPrivateFieldGet(this, _fieldStyle);
                }
                cellTitle.style = Object.assign(Object.assign({}, __classPrivateFieldGet(this, _titleStyle)), { font: Object.assign(Object.assign({}, (_a = __classPrivateFieldGet(this, _titleStyle)) === null || _a === void 0 ? void 0 : _a.font), { color: Object.assign(Object.assign({}, (_c = (_b = __classPrivateFieldGet(this, _titleStyle)) === null || _b === void 0 ? void 0 : _b.font) === null || _c === void 0 ? void 0 : _c.color), { argb: fontColor || ((_f = (_e = (_d = __classPrivateFieldGet(this, _titleStyle)) === null || _d === void 0 ? void 0 : _d.font) === null || _e === void 0 ? void 0 : _e.color) === null || _f === void 0 ? void 0 : _f.argb) }) }), fill: {
                        type: 'pattern',
                        pattern: 'solid',
                        fgColor: {
                            argb: fill || __classPrivateFieldGet(this, _titleFgColor),
                        },
                    } });
                cellField.value = column.field;
                cellTitle.value = column.title;
                if (hasDescription) {
                    cellDescription.style = __classPrivateFieldGet(this, _descriptionStyle);
                    cellDescription.value = column.description || '';
                }
            });
            if (sheets === null || sheets === void 0 ? void 0 : sheets.length) {
                for (const sheet of sheets) {
                    if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.fields)) {
                        const newSheet = workbook.addWorksheet(sheet.name);
                        sheet.fields.forEach((field, index) => {
                            newSheet.getColumn(index + 1).width = 30;
                            newSheet.getCell(1, index + 1).style = __classPrivateFieldGet(this, _titleStyle);
                            newSheet.getCell(1, index + 1).value = field;
                        });
                        sheet.items.forEach((item, idx1) => {
                            sheet.fields.forEach((field, idx2) => {
                                newSheet.getCell(2 + idx1, 1 + idx2).value = item[field];
                                newSheet.getCell(2 + idx1, 1 + idx2).style = __classPrivateFieldGet(this, _cellStyle);
                            });
                        });
                    }
                }
            }
            const file = yield workbook.xlsx.writeBuffer();
            SdUtility.downloadBlob(new Blob([file], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }), fileName);
        });
        this.uploadTemplate = (args) => __awaiter(this, void 0, void 0, function* () {
            const { key, group, validator } = args;
            const { uploadTemplate } = API;
            const url = `${this.functionUrl}${uploadTemplate}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}`;
            const file = yield SdUtility.upload({
                extensions: ['xlsx'],
                maxSizeInMb: 0.1,
                validator,
            });
            if (file) {
                const { filePath, fileName } = yield this.apiService.upload(url, file).catch((err) => {
                    this.notifyService.notify.warning(err === null || err === void 0 ? void 0 : err.message);
                    throw err;
                });
                return {
                    filePath,
                    fileName,
                };
            }
            return null;
        });
        this.generateUploadTemplate = (args) => __awaiter(this, void 0, void 0, function* () {
            const { key, template, group } = args;
            const { generateUploadTemplate } = API;
            const url = `${this.functionUrl}${generateUploadTemplate}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}`;
            const { filePath, fileName } = yield this.apiService.post(url, template);
            return { filePath, fileName };
        });
        this.removeFile = (args) => __awaiter(this, void 0, void 0, function* () {
            const { key, group, fileName } = args;
            const { removeFile } = API;
            const url = `${this.functionUrl}${removeFile}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}&name=${fileName}`;
            yield this.apiService.post(url);
        });
        this.filesInFolder = (args) => __awaiter(this, void 0, void 0, function* () {
            var _a;
            const { key, group } = args;
            const { filesInFolder } = API;
            const url = `${this.functionUrl}${filesInFolder}?${__classPrivateFieldGet(this, _directory).call(this, key, group)}`;
            const res = yield this.apiService.get(url);
            return (((_a = res.files) === null || _a === void 0 ? void 0 : _a.map(e => ({
                filePath: e.publicUrl,
                fileName: e.name,
            }))) || []);
        });
        this.download = (filePath, fileName) => {
            const link = document.createElement('a');
            link.download = `${fileName || v4()}.xlsx`;
            link.href = filePath;
            document.body.appendChild(link);
            link.click();
            document.body.removeChild(link);
        };
        this.exportByTemplate = (args) => __awaiter(this, void 0, void 0, function* () {
            const { filePath, columns, items, fileName } = args;
            const { sdExportByTemplate } = API;
            const url = `${this.functionUrl}${sdExportByTemplate}`;
            const buffer = yield this.apiService.post(url, {
                filePath,
                columns,
                items,
                fileName,
            }, null, {
                responseType: 'arraybuffer',
            });
            const blob = new Blob([buffer], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64,' });
            SdUtility.downloadBlob(blob, fileName);
        });
        this.exportCSV = (option) => __awaiter(this, void 0, void 0, function* () {
            const { columns, items, fileName } = option;
            const headerCSV = {};
            for (const column of columns) {
                headerCSV[column.field] = column.title;
            }
            const csvExporter = new ExportToCsv({
                filename: `${fileName || 'CSV'}_${Date.toFormat(new Date(), 'yyyy-MM-dd-HH-mm-ss')}`,
                fieldSeparator: ',',
                quoteStrings: '"',
                decimalSeparator: '.',
                showLabels: true,
                showTitle: false,
                title: fileName || 'CSV',
                useBom: true,
            });
            csvExporter.generateCsv([headerCSV, ...items]);
        });
        this.export = (option) => __awaiter(this, void 0, void 0, function* () {
            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 = 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 = __classPrivateFieldGet(this, _fieldStyle);
                if (column.required) {
                    firstSheet.getCell(2, index + 1).style = __classPrivateFieldGet(this, _requiredStyle);
                }
                else {
                    firstSheet.getCell(2, index + 1).style = __classPrivateFieldGet(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 = __classPrivateFieldGet(this, _descriptionStyle);
                    firstSheet.getCell(3, index + 1).value = column.description || '';
                }
            });
            if (sheets === null || sheets === void 0 ? void 0 : sheets.length) {
                for (const sheet of sheets) {
                    if (sheet.name && Array.isArray(sheet.items) && Array.isArray(sheet.fields)) {
                        const newSheet = workbook.addWorksheet(sheet.name);
                        sheet.fields.forEach((field, index) => {
                            newSheet.getColumn(index + 1).width = 30;
                            newSheet.getCell(1, index + 1).style = __classPrivateFieldGet(this, _titleStyle);
                            newSheet.getCell(1, index + 1).value = field;
                        });
                        sheet.items.forEach((item, idx1) => {
                            sheet.fields.forEach((field, idx2) => {
                                newSheet.getCell(2 + idx1, 1 + idx2).value = item[field];
                                newSheet.getCell(2 + idx1, 1 + idx2).style = __classPrivateFieldGet(this, _cellStyle);
                            });
                        });
                    }
                }
            }
            const fromRow = hasDescription ? 4 : 3;
            items.forEach((e, idx1) => {
                columns.forEach((column, idx2) => {
                    if (typeof e[column.field] === 'number' && !column.numFmt) {
                        // 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).numFmt = column.numFmt;
                    }
                    firstSheet.getCell(fromRow + idx1, 1 + idx2).style = __classPrivateFieldGet(this, _cellStyle);
                });
            });
            const file = yield workbook.xlsx.writeBuffer();
            SdUtility.downloadBlob(new Blob([file], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }), fileName);
        });
        this.exportCustom = (option) => __awaiter(this, void 0, void 0, function* () {
            const { fileName, sheets } = option;
            if (!(sheets === null || sheets === void 0 ? void 0 : sheets.length)) {
                this.notifyService.notify.warning('Phải có ít nhất 1 sheet');
                return;
            }
            const workbook = new Workbook();
            for (const [idx, sheet] of sheets.entries()) {
                const { name, columns, cells } = sheet;
                const worksheet = workbook.addWorksheet(name || `Sheet ${idx + 1}`);
                for (const column of columns || []) {
                    worksheet.getColumn(column.index).style = column.style;
                    worksheet.getColumn(column.index).width = column.width;
                }
                for (const cell of cells) {
                    const { row, column, value, style } = cell;
                    worksheet.getCell(row, column).style = style || worksheet.getColumn(column).style;
                    worksheet.getCell(row, column).value = value;
                }
            }
            const file = yield workbook.xlsx.writeBuffer();
            SdUtility.downloadBlob(new Blob([file], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' }), fileName);
        });
        this.mergePDF = (urls) => __awaiter(this, void 0, void 0, function* () {
            const { sdMergePDF } = API;
            const url = `${this.functionUrl}${sdMergePDF}`;
            const buffer = yield this.apiService.post(url, {
                urls,
            }, null, {
                responseType: 'arraybuffer',
            });
            SdUtility.downloadBlob(new Blob([buffer], { type: 'application/pdf' }));
        });
        this.uploadXlsx = () => __awaiter(this, void 0, void 0, function* () {
            return yield SdUtility.upload({
                extensions: ['xlsx'],
                maxSizeInMb: 10,
            }).then(file => {
                return this.parseXlsx(file);
            });
        });
        this.parseXlsx = (file) => __awaiter(this, void 0, void 0, function* () {
            if (file) {
                return new Promise((resolve, reject) => {
                    const wb = new Workbook();
                    const reader = new FileReader();
                    reader.onload = () => {
                        const buffer = reader.result;
                        if (!buffer) {
                            reject('Có lỗi xảy ra khi đọc file');
                            return;
                        }
                        wb.xlsx.load(buffer).then(workbook => {
                            const sheet = workbook.worksheets[0];
                            if (!sheet) {
                                reject('Không tìm thấy dữ liệu');
                                return;
                            }
                            const items = [];
                            const headers = sheet.getRow(1).values;
                            if (Array.isArray(headers)) {
                                sheet.eachRow((row, rowIndex) => {
                                    const { hasValues, values } = row;
                                    // console.log(row, hasValues, values)
                                    if (hasValues && rowIndex > 1) {
                                        const item = {};
                                        headers.forEach((cellValue, index) => {
                                            if (cellValue) {
                                                const field = cellValue.toString();
                                                item[field] = values[index];
                                                if (typeof item[field] === 'string') {
                                                    item[field] = item[field].trim();
                                                }
                                                if (item[field] === '' || item[field] === undefined) {
                                                    item[field] = null;
                                                }
                                            }
                                        });
                                        items.push(item);
                                    }
                                });
                                resolve({
                                    items,
                                    file,
                                });
                            }
                        });
                    };
                    reader.readAsArrayBuffer(file);
                });
            }
            else {
                return {
                    items: [],
                    file: null,
                };
            }
        });
    }
    get functionUrl() {
        var _a;
        return (_a = this.firebaseConfiguration) === null || _a === void 0 ? void 0 : _a.functionUrl;
    }
    get folder() {
        const { project, env } = this.firebaseConfiguration;
        return `${project}-${env}`;
    }
    get userFolder() {
        const { folder } = this.firebaseConfiguration;
        if (!folder) {
            return;
        }
        if (typeof folder === 'string') {
            return folder;
        }
        return folder();
    }
}
_fieldStyle = new WeakMap(), _titleColor = new WeakMap(), _titleFgColor = new WeakMap(), _titleStyle = new WeakMap(), _requiredStyle = new WeakMap(), _descriptionStyle = new WeakMap(), _cellStyle = new WeakMap(), _directory = new WeakMap();
SdExportService.ɵprov = ɵɵdefineInjectable({ factory: function SdExportService_Factory() { return new SdExportService(ɵɵinject(SdApiService), ɵɵinject(SdNotifyService), ɵɵinject(FIREBASE_CONFIG, 8)); }, token: SdExportService, providedIn: "root" });
SdExportService.decorators = [
    { type: Injectable, args: [{
                providedIn: 'root',
            },] }
];
SdExportService.ctorParameters = () => [
    { type: SdApiService },
    { type: SdNotifyService },
    { type: undefined, decorators: [{ type: Inject, args: [FIREBASE_CONFIG,] }, { type: Optional }] }
];

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

export { API, SdExportService };
//# sourceMappingURL=sd-angular-core-export.js.map
