function normalizeArabic(text = "") {
 return String(text)
 .toLowerCase()
 .normalize("NFKC")
 .replace(/[\u064B-\u0652]/g, "")
 .replace(/[إأآا]/g, "ا")
 .replace(/ى/g, "ي")
 .replace(/ؤ/g, "و")
 .replace(/ئ/g, "ي")
 .replace(/ة/g, "ه")
 .replace(/\s+/g, " ")
 .trim();
}
function scoreTerm(item, query, terms) {
 if (!query) return 1;
 const term = normalizeArabic(item.title || "");
 const body = normalizeArabic(item.body || "");
 let score = 0;
 if (term === query) score += 150;
 if (term.startsWith(query)) score += 100;
 if (term.includes(query)) score += 60;
 if (body.includes(query)) score += 25;
 const matchedTerms = terms.filter((token) => term.includes(token) || body.includes(token)).length;
 score += matchedTerms * 10;
 return score;
}
function scoreDate(item, query, terms) {
 if (!query) return 1;
 const date = normalizeArabic(item.title || "");
 const body = normalizeArabic(item.body || "");
 let score = 0;
 if (date === query) score += 120;
 if (date.startsWith(query)) score += 85;
 if (date.includes(query)) score += 60;
 if (body.includes(query)) score += 30;
 const matchedTerms = terms.filter((token) => date.includes(token) || body.includes(token)).length;
 score += matchedTerms * 9;
 return score;
}
function getKnowledgeItems(data) {
 return (data.items || []).filter((item) => item.kind !== "subject");
}
function getSubjectItems(data) {
 return (data.items || []).filter((item) => item.kind === "subject");
}
function applyKnowledgeFilters(items, filters) {
 return items.filter((item) => {
 if (filters.module && item.module !== filters.module) return false;
 if (filters.unit && item.unit !== filters.unit) return false;
 if (filters.type === "person" && item.kind !== "person") return false;
 if (filters.type === "term" && item.kind !== "term") return false;
 if (filters.type === "date" && item.kind !== "date") return false;
 return true;
 });
}
export function buildTaxonomy(data) {
 const modules = new Set();
 const units = new Set();
 getKnowledgeItems(data).forEach((item) => {
 if (item.module) modules.add(item.module);
 if (item.unit) units.add(item.unit);
 });
 return {
 modules: Array.from(modules).sort((a, b) => a.localeCompare(b, "ar")),
 units: Array.from(units).sort((a, b) => a.localeCompare(b, "ar"))
 };
}
export function buildSubjectsTaxonomy(data) {
 const branches = new Set();
 const modules = new Map();
 const years = new Map();
 getSubjectItems(data).forEach((item) => {
 if (item.branch) branches.add(item.branch);
 if (!modules.has(item.branch)) modules.set(item.branch, new Set());
 if (item.module) modules.get(item.branch).add(item.module);
 const branchModuleKey = `${item.branch}::${item.module}`;
 if (!years.has(branchModuleKey)) years.set(branchModuleKey, new Set());
 if (item.bacYear) years.get(branchModuleKey).add(item.bacYear);
 });
 const modulesByBranch = {};
 modules.forEach((value, key) => {
 modulesByBranch[key] = Array.from(value).sort((a, b) => a.localeCompare(b, "ar"));
 });
 const yearsByBranchModule = {};
 years.forEach((value, key) => {
 yearsByBranchModule[key] = Array.from(value).sort((a, b) => b.localeCompare(a, "ar"));
 });
 return {
 branches: Array.from(branches).sort((a, b) => a.localeCompare(b, "ar")),
 modulesByBranch,
 yearsByBranchModule
 };
}
export function filterSubjects(data, filters) {
 return getSubjectItems(data)
 .filter((item) => {
 if (filters.branch && item.branch !== filters.branch) return false;
 if (filters.module && item.module !== filters.module) return false;
 if (filters.year && item.bacYear !== filters.year) return false;
 return true;
 })
 .sort((a, b) => {
 const yearCompare = String(b.bacYear || "").localeCompare(String(a.bacYear || ""));
 if (yearCompare !== 0) return yearCompare;
 return String(a.title || "").localeCompare(String(b.title || ""), "ar");
 });
}
export function searchOffline(data, filters) {
 const normalizedQuery = normalizeArabic(filters.q || "");
 const terms = normalizedQuery ? normalizedQuery.split(" ").filter(Boolean) : [];
 const knowledgeItems = applyKnowledgeFilters(getKnowledgeItems(data), filters);
 const scored = knowledgeItems
 .map((item) => {
 const score = item.kind === "date"
 ? scoreDate(item, normalizedQuery, terms)
 : scoreTerm(item, normalizedQuery, terms);
 return { ...item, score };
 })
 .filter((item) => item.score > 0)
 .sort((a, b) => b.score - a.score);
 return {
 total: scored.length,
 items: scored
 };
}
export function pickDailyItems(data) {
 const dayIndex = Math.floor(Date.now() / 86400000);
 const terms = getKnowledgeItems(data).filter((item) => item.kind === "term" || item.kind === "person");
 const dates = getKnowledgeItems(data).filter((item) => item.kind === "date");
 return {
 term: terms.length ? terms[dayIndex % terms.length] : null,
 date: dates.length ? dates[(dayIndex * 3) % dates.length] : null
 };
}