/**
 * Utility for fetching and loading fonts for jsPDF generation.
 * Handles fetching TTF files, converting to base64, and registering with jsPDF.
 */
import { isSystemFont } from './googleFontsManager';
import { cacheFont, getCachedFont } from './fontCacheManager';

// Mapping for reliable TTF sources. 
// We use GitHub raw content for Google Fonts (OFL license) as a reliable source for frontend-only fetching.
const GITHUB_FONTS_BASE = 'https://raw.githubusercontent.com/google/fonts/main/ofl/';
const APACHE_FONTS_BASE = 'https://raw.githubusercontent.com/google/fonts/main/apache/';

// Exceptions or specific paths if the standard naming convention [FamilyName]/[FamilyName]-Regular.ttf doesn't apply
const FONT_PATH_EXCEPTIONS = {
    'Roboto Mono': 'robotomono/RobotoMono[wght].ttf', // Variable font often
    'Source Sans 3': 'sourcesans3/SourceSans3[wght].ttf',
    'Open Sans': 'opensans/OpenSans[wdth,wght].ttf',
    'Montserrat': 'montserrat/Montserrat[wght].ttf',
    'Raleway': 'raleway/Raleway[wght].ttf',
    'Inconsolata': 'inconsolata/Inconsolata[wdth,wght].ttf'
    // Most static fonts follow the pattern
};

// Map fonts to their license folder (ofl is default, apache is exception)
const LICENSE_MAP = {
    'Roboto': 'apache',
    'Open Sans': 'apache'
};

const getFontUrl = (fontName, weight = 'Regular') => {
    // Normalize name for folder: "Open Sans" -> "opensans"
    const folderName = fontName.toLowerCase().replace(/\s+/g, '');
    
    // Normalize name for file: "Open Sans" -> "OpenSans"
    const fileNameBase = fontName.replace(/\s+/g, '');
    
    // Determine license base
    const base = LICENSE_MAP[fontName] === 'apache' ? APACHE_FONTS_BASE : GITHUB_FONTS_BASE;
    
    // Handle variable fonts which are common now. 
    // If it's a variable font, we might need the static fallback if jsPDF doesn't like var fonts, 
    // BUT many Google Fonts repos now only host the variable version in the root.
    // However, usually there is a 'static' folder. 
    // For simplicity in this environment, we will try to fetch the 'Regular' static file from the static folder if it exists,
    // or standard path.
    
    // Construct standard static path first
    // Ex: https://raw.githubusercontent.com/google/fonts/main/ofl/lato/Lato-Regular.ttf
    return `${base}${folderName}/${fileNameBase}-${weight}.ttf`;
};

/**
 * Fetches a font file and converts it to base64.
 * @param {string} fontName 
 * @param {string} weight - 'Regular', 'Bold', 'Italic', 'BoldItalic'
 */
export const loadFontForPdf = async (fontName, weight = 'Regular') => {
    if (!fontName || isSystemFont(fontName)) {
        return null; // System fonts are handled natively by jsPDF or mapped to standard
    }

    const cached = getCachedFont(fontName, weight);
    if (cached) return cached;

    try {
        const url = getFontUrl(fontName, weight);
        console.log(`Fetching font ${fontName} (${weight}) from ${url}`);
        
        const response = await fetch(url);
        if (!response.ok) {
            // Try 'static' folder fallback for variable fonts
            // Ex: .../lato/static/Lato-Regular.ttf
            const folderName = fontName.toLowerCase().replace(/\s+/g, '');
            const fileNameBase = fontName.replace(/\s+/g, '');
            const base = LICENSE_MAP[fontName] === 'apache' ? APACHE_FONTS_BASE : GITHUB_FONTS_BASE;
            const staticUrl = `${base}${folderName}/static/${fileNameBase}-${weight}.ttf`;
            
            console.log(`Retrying with static folder: ${staticUrl}`);
            const response2 = await fetch(staticUrl);
            if (!response2.ok) throw new Error(`Failed to fetch font: ${response.statusText}`);
            
            const blob = await response2.blob();
            const base64 = await blobToBase64(blob);
            cacheFont(fontName, weight, base64);
            return base64;
        }

        const blob = await response.blob();
        const base64 = await blobToBase64(blob);
        
        cacheFont(fontName, weight, base64);
        return base64;
    } catch (error) {
        console.error(`Error loading font ${fontName}:`, error);
        return null;
    }
};

const blobToBase64 = (blob) => {
    return new Promise((resolve, reject) => {
        const reader = new FileReader();
        reader.onloadend = () => {
            if (typeof reader.result === 'string') {
                // remove data:font/ttf;base64, prefix
                const base64 = reader.result.split(',')[1];
                resolve(base64);
            } else {
                reject(new Error('Failed to convert blob'));
            }
        };
        reader.onerror = reject;
        reader.readAsDataURL(blob);
    });
};

/**
 * Registers a font with a jsPDF document instance.
 * @param {Object} doc - jsPDF instance
 * @param {string} fontName - Name of the font
 * @param {string} fontData - Base64 data
 * @param {string} weight - 'normal', 'bold', 'italic', 'bolditalic'
 */
export const registerFontWithJsPdf = (doc, fontName, fontData, weight = 'normal') => {
    if (!fontData) return;
    
    const fileName = `${fontName}-${weight}.ttf`;
    
    // Add to VFS
    if (!doc.existsFileInVFS(fileName)) {
        doc.addFileToVFS(fileName, fontData);
    }
    
    // Add font
    // Weights map: Regular->normal, Bold->bold
    const style = weight.toLowerCase().replace('regular', 'normal');
    doc.addFont(fileName, fontName, style);
    console.log(`Registered font ${fontName} ${style} with jsPDF`);
};