import { nextTick } from 'vue';
import * as svg from '@element-plus/icons-vue';

function isIconfontStylesheetHref(href: string): boolean {
	if (!href) return false;
	const h = href.toLowerCase();
	return h.includes('at.alicdn.com') || h.includes('iconfont.css') || h.includes('/iconfont/') || h.includes('\\iconfont\\');
}

async function iconClassListFromLocalIconfontJson(): Promise<string[]> {
	const mod: { default?: { css_prefix_text?: string; glyphs?: { font_class: string }[] }; css_prefix_text?: string; glyphs?: { font_class: string }[] } =
		await import('/@/assets/iconfont/iconfont.json');
	const data = mod.default ?? mod;
	const prefix = data.css_prefix_text ?? 'icon-';
	const glyphs = data.glyphs ?? [];
	return glyphs.map((g) => `${prefix}${g.font_class}`);
}

// 获取阿里字体图标（CDN 或本地打包的 iconfont.css；解析失败时用 iconfont.json 兜底，便于纯内网）
const getAlicdnIconfont = () => {
	return new Promise<string[]>((resolve, reject) => {
		nextTick(async () => {
			const styles = document.styleSheets as unknown as CSSStyleSheet[];
			const sheetsList: CSSStyleSheet[] = [];
			for (let i = 0; i < styles.length; i++) {
				const sheet = styles[i];
				const href = sheet.href || '';
				if (isIconfontStylesheetHref(href)) sheetsList.push(sheet);
			}
			const sheetsIconList: string[] = [];
			for (let i = 0; i < sheetsList.length; i++) {
				const rules = safeReadCssRules(sheetsList[i]);
				if (!rules) continue;
				try {
					for (let j = 0; j < rules.length; j++) {
						const rule = rules[j] as CSSStyleRule;
						const sel = rule.selectorText;
						if (sel && sel.indexOf('.icon-') > -1) {
							sheetsIconList.push(`${sel.substring(1, sel.length).replace(/\:\:before/gi, '')}`);
						}
					}
				} catch {
					continue;
				}
			}
			if (sheetsIconList.length > 0) {
				resolve(sheetsIconList);
				return;
			}
			try {
				const fromJson = await iconClassListFromLocalIconfontJson();
				if (fromJson.length > 0) {
					resolve(fromJson);
					return;
				}
			} catch {
				// ignore
			}
			reject('未获取到值，请刷新重试');
		});
	});
};

// 初始化获取 css 样式，获取 element plus 自带 svg 图标，增加了 ele- 前缀，使用时：ele-Aim
const getElementPlusIconfont = () => {
	return new Promise((resolve, reject) => {
		nextTick(() => {
			const icons = svg as any;
			const sheetsIconList = [];
			for (const i in icons) {
				sheetsIconList.push(`ele-${icons[i].name}`);
			}
			if (sheetsIconList.length > 0) resolve(sheetsIconList);
			else reject('未获取到值，请刷新重试');
		});
	});
};

/** 外链样式表因 CORS 无法读 cssRules；FA6 的 font-family 也不是单一的 FontAwesome */
const FA_STYLESHEET_HREF_MARKERS = ['font-awesome', 'fontawesome', 'netdna.bootstrapcdn.com/font-awesome', 'cdnjs.cloudflare.com/ajax/libs/font-awesome', 'use.fontawesome.com'];

const FA_COMPOUND_SKIP = new Set(['fa-solid', 'fa-regular', 'fa-brands']);

function safeReadCssRules(sheet: CSSStyleSheet): CSSRuleList | null {
	try {
		return sheet.cssRules || (sheet as CSSStyleSheet & { rules?: CSSRuleList }).rules || null;
	} catch {
		return null;
	}
}

function fontFamilyLooksLikeFontAwesome(fontFamily: string): boolean {
	if (!fontFamily) return false;
	const f = fontFamily.replace(/['"]/g, '').toLowerCase();
	return f.includes('fontawesome') || f.includes('font awesome');
}

/** 从选择器中提取图标类名，如 .fa-home::before、.fa-solid.fa-user::before */
function extractFaIconClassFromSelector(selectorText: string): string | null {
	if (!selectorText || selectorText.includes(',')) return null;
	if (!/::before|:before/i.test(selectorText)) return null;
	const beforePart = selectorText.split(/::before|:before/i)[0];
	const found = [...beforePart.matchAll(/\.(fa-[a-z0-9-]+)/gi)].map((m) => m[1].toLowerCase());
	const candidates = found.filter((c) => !FA_COMPOUND_SKIP.has(c));
	if (candidates.length === 0) return null;
	return candidates[candidates.length - 1];
}

async function loadFontAwesomeFallbackList(): Promise<string[]> {
	const mod: { default?: string[] } | string[] = await import('e-icon-picker/icon/fontawesome/font-awesome.v4.7.0.js');
	const list = Array.isArray(mod) ? mod : mod.default;
	if (!Array.isArray(list)) return [];
	return list
		.map((entry: string) => {
			const t = String(entry).trim();
			const m = t.match(/^fa\s+(fa-[a-z0-9-]+)/i);
			return m ? m[1] : '';
		})
		.filter(Boolean);
}

// 初始化获取 css 样式，这里使用 fontawesome 的图标（解析失败时用 e-icon-picker 内置列表兜底）
const getAwesomeIconfont = () => {
	return new Promise<string[]>((resolve, reject) => {
		nextTick(async () => {
			const styles = document.styleSheets as unknown as CSSStyleSheet[];
			const sheetsSet = new Set<CSSStyleSheet>();

			for (let i = 0; i < styles.length; i++) {
				const sheet = styles[i];
				const href = (sheet.href || '').toLowerCase();
				if (FA_STYLESHEET_HREF_MARKERS.some((m) => href.includes(m))) {
					sheetsSet.add(sheet);
					continue;
				}
				const rules = safeReadCssRules(sheet);
				if (!rules) continue;
				try {
					for (let j = 0; j < rules.length; j++) {
						const rule = rules[j] as CSSStyleRule;
						if (rule.style && fontFamilyLooksLikeFontAwesome(rule.style.fontFamily || '')) {
							sheetsSet.add(sheet);
							break;
						}
					}
				} catch {
					continue;
				}
			}

			const seen = new Set<string>();
			const sheetsIconList: string[] = [];
			for (const sh of sheetsSet) {
				const rules = safeReadCssRules(sh);
				if (!rules) continue;
				try {
					for (let j = 0; j < rules.length; j++) {
						const rule = rules[j] as CSSStyleRule;
						const iconClass = extractFaIconClassFromSelector(rule.selectorText || '');
						if (!iconClass || seen.has(iconClass)) continue;
						seen.add(iconClass);
						sheetsIconList.push(iconClass);
					}
				} catch {
					continue;
				}
			}

			if (sheetsIconList.length > 0) {
				resolve([...sheetsIconList].reverse());
				return;
			}

			const fallback = await loadFontAwesomeFallbackList();
			if (fallback.length > 0) {
				resolve(fallback);
				return;
			}

			reject('未获取到值，请刷新重试');
		});
	});
};

/**
 * 获取字体图标 `document.styleSheets`
 * @method ali 获取阿里字体图标 `<i class="iconfont 图标类名"></i>`
 * @method ele 获取 element plus 自带图标 `<i class="图标类名"></i>`
 * @method ali 获取 fontawesome 的图标 `<i class="fa 图标类名"></i>`
 */
const initIconfont = {
	// iconfont
	ali: () => {
		return getAlicdnIconfont();
	},
	// element plus
	ele: () => {
		return getElementPlusIconfont();
	},
	// fontawesome
	awe: () => {
		return getAwesomeIconfont();
	},
};

// 导出方法
export default initIconfont;
