/**
 * Word (.doc / .docx) → HTML 导入
 */
import mammoth from 'mammoth';
import JSZip from 'jszip';

var MAMMOTH_STYLE_MAP = [
	"p[style-name='Title'] => h1.ct-word-doc-title:fresh",
	"p[style-name='Heading 1'] => p.ct-word-section-title:fresh",
	"p[style-name='Heading 2'] => p.ct-word-section-title.ct-word-section-title--2:fresh",
	"p[style-name='Heading 3'] => p.ct-word-section-title.ct-word-section-title--3:fresh",
	"p[style-name='标题'] => p.ct-word-section-title:fresh",
	"p[style-name='标题 1'] => p.ct-word-section-title:fresh",
	"p[style-name='标题1'] => p.ct-word-section-title:fresh",
	"p[style-name='标题 2'] => p.ct-word-section-title.ct-word-section-title--2:fresh",
	"p[style-name='标题2'] => p.ct-word-section-title.ct-word-section-title--2:fresh",
	"p[style-name='标题 3'] => p.ct-word-section-title.ct-word-section-title--3:fresh",
	"p[style-name='标题3'] => p.ct-word-section-title.ct-word-section-title--3:fresh",
	"highlight => mark.ct-word-highlight",
	"r[style-name='Highlight'] => mark.ct-word-highlight",
	"r[style-name='高亮强调'] => mark.ct-word-highlight",
];

var OLE_METADATA_PATTERNS = [
	/Root Entry/i,
	/SummaryInformation/i,
	/DocumentSummaryInformation/i,
	/\bWordDocument\b/,
	/WpsCustomData/i,
	/MsoDataStore/i,
	/PKSOProductBuildVer/i,
	/KSOProductBuildVer/i,
	/\bICV\b/,
	/\bFormText\b/,
	/MERGEFORMAT/i,
	/OLE_LINK/i,
];

var LEGACY_DOC_JUNK_EXACT = {
	'Root Entry': true,
	'SummaryInformation': true,
	'DocumentSummaryInformation': true,
	'WordDocument': true,
	'Word.Document': true,
	'Data': true,
	'1Table': true,
	'WpsCustomData': true,
	'MsoDataStore': true,
	'Normal': true,
	'Default Paragraph Font': true,
	'Table Normal': true,
};

export var IMPORTED_WORD_STYLE_ELEMENT_ID = 'ct-imported-word-styles';

export function buildImportedWordBaselineCss() {
	return [
		'.ct-word-doc--imported{font-family:SimSun,"宋体","Songti SC",STSong,serif;font-size:11pt;line-height:1.15;color:#000;letter-spacing:normal;word-break:normal;overflow-wrap:break-word}',
		'.ct-word-doc--imported p,.ct-word-doc--imported li{margin:0;text-align:inherit;text-indent:inherit}',
		'.ct-word-doc--imported h1,.ct-word-doc--imported h2,.ct-word-doc--imported h3,.ct-word-doc--imported h4,.ct-word-doc--imported h5,.ct-word-doc--imported h6{margin:0;font-size:inherit;font-weight:inherit;line-height:inherit}',
		'.ct-word-doc--imported .ct-word-section-title{font-weight:700;margin:0;text-align:justify}',
		'.ct-word-doc--imported .ct-word-doc-title{text-align:center;font-weight:700;font-size:18pt;margin:0 0 6pt}',
		'.ct-word-doc--imported mark.ct-word-highlight,.ct-word-doc--imported .ct-word-highlight{background-color:#ffff00;color:inherit;padding:0}',
		'.ct-word-doc--imported table{border-collapse:collapse;width:auto;max-width:100%;table-layout:auto}',
		'.ct-word-doc--imported td,.ct-word-doc--imported th{vertical-align:top}',
		'.ct-word-doc--imported img{max-width:100%;height:auto}',
		'.ct-word-doc--imported strong,.ct-word-doc--imported b{font-weight:700}',
	].join('\n');
}

function scopeCssToImportedRoot(cssText) {
	var scoped = String(cssText || '').trim();
	if (!scoped) return '';
	if (scoped.indexOf('.ct-word-doc--imported') >= 0) return scoped;
	return scoped.replace(/(^|\})([^{@]+)\{/g, function (match, prefix, selector) {
		var parts = selector.split(',').map(function (part) {
			var trimmed = part.trim();
			if (!trimmed || trimmed.indexOf('@') === 0) return trimmed;
			return '.ct-word-doc--imported ' + trimmed;
		});
		return prefix + parts.join(',') + '{';
	});
}

export function extractInlineStylesFromImportedHtml(html) {
	var content = String(html || '');
	var cssParts = [];
	content = content.replace(/<style[^>]*>([\s\S]*?)<\/style>/gi, function (_, css) {
		if (css && css.trim()) cssParts.push(css.trim());
		return '';
	});
	var cssText = cssParts.map(scopeCssToImportedRoot).filter(Boolean).join('\n');
	return { html: content.trim(), cssText: cssText };
}

export async function extractDocxThemeStyles(arrayBuffer) {
	try {
		var zip = await JSZip.loadAsync(arrayBuffer);
		var stylesFile = zip.file('word/styles.xml');
		if (!stylesFile) return '';
		var stylesXml = await stylesFile.async('text');
		var fontFamily = '宋体';
		var fontSize = '11pt';
		var docDefaultsMatch = stylesXml.match(/<w:docDefaults[\s\S]*?<\/w:docDefaults>/);
		if (docDefaultsMatch) {
			var block = docDefaultsMatch[0];
			var eastAsia = block.match(/w:eastAsia="([^"]+)"/);
			if (eastAsia && eastAsia[1]) fontFamily = eastAsia[1];
			var ascii = block.match(/w:ascii="([^"]+)"/);
			if (!eastAsia && ascii && ascii[1]) fontFamily = ascii[1];
			var sz = block.match(/<w:sz[^>]*w:val="(\d+)"/);
			if (sz && sz[1]) fontSize = (parseInt(sz[1], 10) / 2) + 'pt';
		}
		return '.ct-word-doc--imported{font-family:"' + fontFamily + '",SimSun,"宋体","Songti SC",serif;font-size:' + fontSize + ';line-height:1.15;color:#000}';
	} catch (e) {
		return '';
	}
}

export function injectImportedWordStyles(cssText) {
	if (typeof document === 'undefined') return;
	var merged = [buildImportedWordBaselineCss(), String(cssText || '').trim()].filter(Boolean).join('\n');
	var styleEl = document.getElementById(IMPORTED_WORD_STYLE_ELEMENT_ID);
	if (!styleEl) {
		styleEl = document.createElement('style');
		styleEl.id = IMPORTED_WORD_STYLE_ELEMENT_ID;
		document.head.appendChild(styleEl);
	}
	if (styleEl.textContent !== merged) styleEl.textContent = merged;
}

export function prepareImportedWordHtml(html, extraCss) {
	var source = sanitizeImportedWordHtml(String(html || ''));
	if (!isImportedWordDocHtml(source)) return source;
	var extracted = extractInlineStylesFromImportedHtml(source);
	injectImportedWordStyles([extracted.cssText, extraCss].filter(Boolean).join('\n'));
	var body = extracted.html.trim();
	if (!body) return '';
	if (body.indexOf('ct-word-doc--imported') >= 0) return body;
	return wrapWordHtml(body);
}

function wrapWordHtml(html) {
	var body = String(html || '').trim();
	if (!body) return '';
	if (body.indexOf('ct-word-doc') >= 0) return body;
	return '<div class="ct-word-doc ct-word-doc--imported">' + body + '</div>';
}

function escapeHtml(text) {
	return String(text || '')
		.replace(/&/g, '&amp;')
		.replace(/</g, '&lt;')
		.replace(/>/g, '&gt;');
}

function detectWordFileFormat(arrayBuffer) {
	var view = new Uint8Array(arrayBuffer || []);
	if (view.length >= 4 && view[0] === 0x50 && view[1] === 0x4b) return 'docx';
	if (view.length >= 8 && view[0] === 0xd0 && view[1] === 0xcf && view[2] === 0x11 && view[3] === 0xe0) return 'doc';
	return 'unknown';
}

export function isImportedWordDocHtml(html) {
	return /ct-word-doc--imported/.test(String(html || ''));
}

export function isCorruptWordImportHtml(html) {
	var source = String(html || '');
	if (!source.trim()) return true;
	var plain = source.replace(/<style[^>]*>[\s\S]*?<\/style>/gi, '').replace(/<[^>]+>/g, '');
	if (!plain.replace(/\s/g, '')) return true;
	var hits = 0;
	OLE_METADATA_PATTERNS.forEach(function (pattern) {
		if (pattern.test(plain)) hits += 1;
	});
	if (hits >= 2) return true;
	if (/[\u4e00-\u9fff]/.test(plain)) return false;
	if (/合同|甲方|乙方|租赁|附件/.test(plain)) return false;
	return hits >= 1 && plain.length < 500;
}

export function sanitizeImportedWordHtml(html) {
	var content = String(html || '').trim();
	if (!content) return '';
	content = content
		.replace(/<\/p>\s*n\s*<p/gi, '</p><p')
		.replace(/<\/table>\s*n\s*<p/gi, '</table><p')
		.replace(/<\/table>\s*n\s*<table/gi, '</table><table');
	if (content.indexOf('ct-word-doc--imported') < 0 && content.indexOf('ct-word-doc') >= 0) {
		content = content.replace('ct-word-doc', 'ct-word-doc ct-word-doc--imported');
	}
	return content;
}

function looksLikeHeadingLine(line) {
	var text = String(line || '').trim();
	if (!text || text.length > 80) return false;
	if (/^附件\s*\d+/i.test(text)) return true;
	if (/^第[一二三四五六七八九十\d]+[章节部分]/i.test(text)) return true;
	if (/^[一二三四五六七八九十\d]+[、.:：]/.test(text) && text.length <= 40) return true;
	return text.length <= 24 && !/[。；，,;]/.test(text);
}

function isLegacyDocJunkLine(line) {
	var text = String(line || '').trim();
	if (!text) return true;
	if (LEGACY_DOC_JUNK_EXACT[text]) return true;
	if (/^Text\d+$/i.test(text)) return true;
	if (/^P\s*\d+$/i.test(text)) return true;
	if (/^[\d\s*桰漀]+$/.test(text)) return true;
	if (text.length <= 28 && !/[\u4e00-\u9fff]/.test(text) && /^[\x00-\x7F\s]+$/.test(text)) return true;
	if (OLE_METADATA_PATTERNS.some(function (pattern) { return pattern.test(text); })) return true;
	return false;
}

function plainTextToHtml(text) {
	var lines = String(text || '')
		.replace(/\r/g, '\n')
		.split('\n')
		.map(function (line) { return line.trim(); })
		.filter(function (line) { return line && !isLegacyDocJunkLine(line); });
	if (!lines.length) return '';
	return lines.map(function (line) {
		if (looksLikeHeadingLine(line)) {
			return '<p class="ct-word-section-title">' + escapeHtml(line) + '</p>';
		}
		return '<p class="ct-word-body">' + escapeHtml(line) + '</p>';
	}).join('');
}

/** 从旧版 .doc 二进制中粗提取可读文本（原型层兜底） */
function extractTextFromLegacyDoc(arrayBuffer) {
	var view = new Uint8Array(arrayBuffer);
	var chunks = [];
	var current = '';

	function flush() {
		var text = current.replace(/\s+/g, ' ').trim();
		if (text.length >= 4 && !isLegacyDocJunkLine(text)) chunks.push(text);
		current = '';
	}

	for (var i = 0; i < view.length - 1; i += 2) {
		var code = view[i] | (view[i + 1] << 8);
		if (
			(code >= 0x20 && code <= 0x7e)
			|| (code >= 0x4e00 && code <= 0x9fff)
			|| code === 0x0a
			|| code === 0x0d
			|| code === 0x3001
			|| code === 0x3002
			|| code === 0xff1a
			|| code === 0xff1b
		) {
			current += String.fromCharCode(code);
		} else {
			flush();
		}
	}
	flush();

	var merged = chunks.join('\n');
	if (!merged.trim()) {
		var latin = new TextDecoder('latin1').decode(view);
		merged = latin.replace(/[^\x20-\x7E\u4e00-\u9fff\r\n]+/g, '\n');
	}
	return merged.replace(/\n{3,}/g, '\n\n').trim();
}

export async function convertDocxArrayBufferToHtml(arrayBuffer) {
	if (detectWordFileFormat(arrayBuffer) !== 'docx') {
		throw new Error('不是有效的 .docx 文件');
	}
	var themeCss = await extractDocxThemeStyles(arrayBuffer);
	var result = await mammoth.convertToHtml(
		{ arrayBuffer: arrayBuffer },
		{
			styleMap: MAMMOTH_STYLE_MAP,
			includeDefaultStyleMap: true,
			includeEmbeddedStyleMap: true,
			ignoreEmptyParagraphs: false,
		}
	);
	var html = String(result.value || '').trim();
	if (!html || isCorruptWordImportHtml(html)) {
		var messages = (result.messages || []).map(function (m) { return m.message; }).filter(Boolean);
		throw new Error(messages[0] || 'Word 文件解析结果无效');
	}
	return prepareImportedWordHtml(wrapWordHtml(html), themeCss);
}

export async function convertDocxFileToHtml(file) {
	if (!file) throw new Error('未选择文件');
	var arrayBuffer = await file.arrayBuffer();
	return convertDocxArrayBufferToHtml(arrayBuffer);
}

export async function convertLegacyDocFileToHtml(file) {
	if (!file) throw new Error('未选择文件');
	var arrayBuffer = await file.arrayBuffer();
	if (detectWordFileFormat(arrayBuffer) !== 'doc') {
		throw new Error('不是有效的 .doc 文件');
	}
	var text = extractTextFromLegacyDoc(arrayBuffer);
	if (!text || !/[\u4e00-\u9fff]/.test(text)) {
		throw new Error('未能从 .doc 文件中提取正文，请另存为 .docx 后重试');
	}
	var html = plainTextToHtml(text);
	if (!html || isCorruptWordImportHtml(html)) {
		throw new Error('未能从 .doc 文件中生成可用内容，请另存为 .docx 后重试');
	}
	return prepareImportedWordHtml(wrapWordHtml(html), '');
}

export async function convertWordFileToHtml(file) {
	if (!file) throw new Error('未选择文件');
	var arrayBuffer = await file.arrayBuffer();
	var format = detectWordFileFormat(arrayBuffer);
	var name = String(file.name || '').toLowerCase();

	if (format === 'docx' || (/\.docx$/i.test(name) && format !== 'doc')) {
		return convertDocxArrayBufferToHtml(arrayBuffer);
	}
	if (format === 'doc' || /\.doc$/i.test(name)) {
		return convertLegacyDocFileToHtml(file);
	}
	throw new Error('无法识别 Word 文件格式，请使用 .doc 或 .docx');
}

export function detectWordFileFormatFromName(name, arrayBuffer) {
	if (arrayBuffer) return detectWordFileFormat(arrayBuffer);
	var lower = String(name || '').toLowerCase();
	if (/\.docx$/i.test(lower)) return 'docx';
	if (/\.doc$/i.test(lower)) return 'doc';
	return 'unknown';
}

export function isDocxArrayBuffer(arrayBuffer) {
	return detectWordFileFormat(arrayBuffer) === 'docx';
}
