export class DocumentFormatter {
    static MONTHS_ID = ['Jan', 'Feb', 'Mar', 'Apr', 'Mei', 'Jun', 'Jul', 'Agu', 'Sep', 'Okt', 'Nov', 'Des'];

    static CATEGORY_RULES = [
        { key: 'skripsi', match: ['skripsi', 'tugas akhir', 'ta'] },
        { key: 'akademik', match: ['akademik', 'kalender', 'kaldik'] },
        { key: 'praktik', match: ['praktik', 'praktek', 'kerja praktik', 'kp'] },
    ];

    static TAG_ABBREVIATIONS = new Set(['kp', 'sop', 'ta', 'krs', 'khs', 'sks', 'pkl', 'mbkm']);

    static FILE_TYPE_RULES = [
        { extensions: ['pdf'], mimeTypes: ['application/pdf'], icon: 'fas fa-file-pdf', css: 'doc-type-pdf' },
        {
            extensions: ['doc', 'docx'],
            mimeTypes: [
                'application/msword',
                'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
            ],
            fallbackType: 'docx',
            icon: 'fas fa-file-word',
            css: 'doc-type-docx',
        },
        {
            extensions: ['ppt', 'pptx'],
            mimeTypes: [
                'application/vnd.ms-powerpoint',
                'application/vnd.openxmlformats-officedocument.presentationml.presentation',
            ],
            fallbackType: 'pptx',
            icon: 'fas fa-file-powerpoint',
            css: 'doc-type-pptx',
        },
        {
            extensions: ['xls', 'xlsx'],
            mimeTypes: [
                'application/vnd.ms-excel',
                'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
            ],
            fallbackType: 'xlsx',
            icon: 'fas fa-file-excel',
            css: 'doc-type-xlsx',
        },
        { extensions: ['csv'], mimeTypes: ['text/csv'], icon: 'fas fa-file-csv', css: 'doc-type-xlsx' },
        { extensions: ['txt', 'rtf', 'md'], mimeTypes: ['text/plain', 'application/rtf'], icon: 'fas fa-file-alt', css: 'doc-type-txt' },
        {
            extensions: ['zip', 'rar', '7z', 'tar', 'gz'],
            mimeTypes: ['application/zip', 'application/x-rar-compressed', 'application/x-7z-compressed', 'application/gzip'],
            icon: 'fas fa-file-archive',
            css: 'doc-type-archive',
        },
        {
            extensions: ['jpg', 'jpeg', 'png', 'gif', 'svg', 'webp'],
            mimePrefix: 'image/',
            icon: 'fas fa-file-image',
            css: 'doc-type-image',
        },
    ];

    static formatDate(iso) {
        if (!iso) return '';
        const date = new Date(iso);
        if (Number.isNaN(date.getTime())) return '';
        const day = String(date.getDate()).padStart(2, '0');
        const month = this.MONTHS_ID[date.getMonth()];
        return `${day} ${month} ${date.getFullYear()}`;
    }

    static categoryFromTags(tags) {
        if (!tags || tags.length === 0) return 'umum';
        const lower = tags.map(tag => tag.toLowerCase());
        for (const rule of this.CATEGORY_RULES) {
            if (rule.match.some(match => lower.includes(match))) return rule.key;
        }
        return 'umum';
    }

    static fileTypeFromName(name) {
        return this.fileInfoFromName(name).type;
    }

    static fileInfoFromName(name) {
        const extension = this.extensionFromName(name);
        const rule = this.FILE_TYPE_RULES.find(item => item.extensions.includes(extension));

        if (!rule) {
            return {
                type: extension || 'file',
                icon: 'fas fa-file',
                css: 'doc-type-file',
            };
        }

        return {
            type: extension,
            icon: rule.icon,
            css: rule.css,
        };
    }

    static fileInfoFromItem(item) {
        const file = item?.file && typeof item.file === 'object' ? item.file : {};
        const nameCandidates = [
            file.filename_download,
            file.filename_disk,
            item?.nama_berkas,
        ];

        for (const name of nameCandidates) {
            const info = this.fileInfoFromName(name);
            if (info.type !== 'file') return info;
        }

        return this.fileInfoFromMime(file.type);
    }

    static fileInfoFromMime(type) {
        const mime = String(type || '').trim().toLowerCase();
        if (!mime) return this.fileInfoFromName('');

        const rule = this.FILE_TYPE_RULES.find(item => (
            item.mimeTypes?.includes(mime) || (item.mimePrefix && mime.startsWith(item.mimePrefix))
        ));

        if (!rule) return this.fileInfoFromName('');

        return {
            type: rule.fallbackType || rule.extensions[0],
            icon: rule.icon,
            css: rule.css,
        };
    }

    static extensionFromName(name) {
        const normalized = String(name || '').trim().toLowerCase();
        const lastSegment = normalized.split(/[\\/]/).pop() || '';
        const extensionStart = lastSegment.lastIndexOf('.');

        if (extensionStart <= 0 || extensionStart === lastSegment.length - 1) return '';
        return lastSegment.slice(extensionStart + 1);
    }

    static downloadFilename(name, type) {
        const ext = `.${type}`;
        if (!name) return `dokumen${ext}`;
        return name.toLowerCase().endsWith(ext.toLowerCase()) ? name : `${name}${ext}`;
    }

    static downloadFilenameFromItem(item) {
        const file = item?.file && typeof item.file === 'object' ? item.file : {};
        const originalFilename = file.filename_download || file.filename_disk;
        if (originalFilename) return originalFilename;

        const fileType = this.fileInfoFromItem(item).type;
        return this.downloadFilename(item?.nama_berkas || 'dokumen', fileType);
    }

    static escapeHtml(str) {
        if (str == null) return '';
        return String(str)
            .replace(/&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');
    }

    static escapeAttr(str) {
        return this.escapeHtml(str);
    }

    static formatTag(tag) {
        const value = String(tag).trim().replace(/\s+/g, ' ');
        if (!value) return value;

        return value.split(' ').map(word => {
            const lower = word.toLowerCase();
            if (this.TAG_ABBREVIATIONS.has(lower) || /^[A-Z0-9]{2,}$/.test(word)) {
                return lower.toUpperCase();
            }

            return lower.charAt(0).toUpperCase() + lower.slice(1);
        }).join(' ');
    }

    static parseTags(raw) {
        if (!raw) return [];
        const str = String(raw).trim();
        if (!str) return [];

        if (str.startsWith('[')) {
            try {
                const arr = JSON.parse(str);
                if (Array.isArray(arr)) {
                    return arr.map(tag => String(tag).trim()).filter(Boolean);
                }
            } catch {
                // Fall through to comma-separated parsing.
            }
        }

        return str.split(',').map(tag => tag.trim()).filter(Boolean);
    }
}
