function calculateSimilarity(title, keyword) {
    const titleLower = title.toLowerCase();
    const keywordLower = keyword.toLowerCase();
    
    if (titleLower === keywordLower) return 1000;
    
    if (titleLower.startsWith(keywordLower)) return 800;
    
    if (titleLower.includes(keywordLower)) return 600;
    
    let matches = 0;
    for (let i = 0; i < Math.min(titleLower.length, keywordLower.length); i++) {
        if (titleLower[i] === keywordLower[i]) matches++;
        else break;
    }
    
    return matches;
}

async function searchResults(keyword) {
    const results = [];
    try {
        const response = await fetchv2("https://triton.squid.wtf/search/?s=" + encodeURIComponent(keyword));
        const data = await response.json();

        const items = data.data?.items || data.items || [];
        if (Array.isArray(items)) {
            for (const item of items) {

                let imageUrl = "";
                if (item.album && item.album.cover) {
                    const cover = item.album.cover.replace(/-/g, '/');
                    imageUrl = `https://resources.tidal.com/images/${cover}/1280x1280.jpg`;
                }

                const qualityDisplay = getQualityDisplay(item.audioQuality);
                const title = `${item.title || "Unknown Title"} • ${qualityDisplay}`;
                const href = `https://hund.qqdl.site/track/?id=${item.id}&quality=${item.audioQuality}`;

                results.push({
                    title: title,
                    image: imageUrl,
                    href: href,
                    baseTitle: item.title || "Unknown Title",
                    similarity: calculateSimilarity(item.title || "Unknown Title", keyword)
                });
            }
        }

        results.sort((a, b) => b.similarity - a.similarity);
        
        results.forEach(r => {
            delete r.baseTitle;
            delete r.similarity;
        });

        return JSON.stringify(results);
    } catch (err) {
        console.error("Search error:", err);
        return JSON.stringify([{
            title: "Error",
            image: "Error",
            href: "Error"
        }]);
    }
}

function getQualityDisplay(quality) {
    const qualityMap = {
        "LOSSLESS": "Hi-Res",
        "HIRES_LOSSLESS": "Hi-Res Lossless",
        "HIGH": "High",
        "LOW": "Low",
        "DOLBY_ATMOS": "Dolby Atmos"
    };
    return qualityMap[quality] || quality || "Unknown";
}

async function extractDetails(url) {
    return JSON.stringify([{
        description: "",
        aliases: "",
        airdate: ""
    }]);
}

async function extractEpisodes(url) {
    const results = [];
    try {
        results.push({
            href: url,
            number: 1
        });
        return JSON.stringify(results);
    } catch (err) {
        return JSON.stringify([{
            href: "Error",
            number: "Error"
        }]);
    }
}

function decodeBase64(str) {
    const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
    let result = '';
    let i = 0;
    
    str = str.replace(/=+$/, '');
    
    while (i < str.length) {
        const a = chars.indexOf(str.charAt(i++));
        const b = chars.indexOf(str.charAt(i++));
        const c = i < str.length ? chars.indexOf(str.charAt(i++)) : 0;
        const d = i < str.length ? chars.indexOf(str.charAt(i++)) : 0;
        
        const bitmap = (a << 18) | (b << 12) | (c << 6) | d;
        
        result += String.fromCharCode((bitmap >> 16) & 255);
        if (c != 64) result += String.fromCharCode((bitmap >> 8) & 255);
        if (d != 64) result += String.fromCharCode(bitmap & 255);
    }
    
    return result;
}

async function extractStreamUrl(url) {
    try {
        const response = await fetchv2(url);
        const data = await response.json();
            
        if (!data.data) {
            console.error("No data field in response");
            return "https://error.org/";
        }
        
        if (!data.data.manifest) {
            console.error("No manifest field in response");
            return "https://error.org/";
        }
        
        try {
            const manifestString = data.data.manifest.trim();
            
            let decodedManifest = decodeBase64(manifestString);
            
            decodedManifest = decodedManifest.replace(/\0/g, '').trim();
            
            const manifestJson = JSON.parse(decodedManifest);
            
            if (manifestJson.urls && manifestJson.urls.length > 0) {
                return manifestJson.urls[0];
            } else {
                console.error("No URLs found in manifest");
            }
        } catch (err) {
            console.error("Failed to decode/parse manifest:", err.message, err.stack);
        }
        
        return "https://error.org/";
    } catch (err) {
        console.error("Extract stream URL error:", err.message, err.stack);
        return "https://error.org/";
    }
}