import {
	QUICK_ENTRY_SLOT_COUNT,
	mapSidebarIconToQuickClass,
	pickPreferredQuickSlotIds,
	type QuickEntryMenuOption,
} from './quickEntry';
import * as workbenchApi from './userWorkbenchShortcutApi';

/**
 * 写入后端时使用的字段名（若与你们序列化器不一致，只改此一处）
 */
export const WORKBENCH_SHORTCUT_WRITE = {
	path: 'web_path',
	sort: 'sort',
	frequent: 'is_frequent',
	/**
	 * 与 `index.vue` 中「标记为常用 / 橙色高亮」单选一致：仅当前选中的槽为 true。
	 * 若你们后端用 `is_active` 表示「该条已启用、五条均为 true」，勿把该字段与单选混用，见文档说明。
	 */
	active: 'is_active',
	/** 展示名，与后端模型 `name` 对齐；若字段名不同只改此处 */
	name: 'name',
	/** 跳转地址（与路由 path 一致即可；别名字段只改此处） */
	link: 'link',
	/** 图标，与 `QuickEntryMenuOption.iconClass` 一致（侧栏 `meta.icon` 映射的 FontAwesome 类名） */
	icon: 'icon',
} as const;

type RawRow = Record<string, unknown> & { id?: string | number };

function readString(obj: unknown, keys: readonly string[]): string | null {
	if (obj === null || typeof obj !== 'object') return null;
	const o = obj as Record<string, unknown>;
	for (const k of keys) {
		const v = o[k];
		if (typeof v === 'string' && v.trim()) return v.trim();
	}
	const menu = o.menu;
	if (menu && typeof menu === 'object') {
		for (const k of keys) {
			const v = (menu as Record<string, unknown>)[k];
			if (typeof v === 'string' && v.trim()) return v.trim();
		}
	}
	return null;
}

function maybeStripHttpPath(s: string): string {
	if (!/^https?:\/\//i.test(s)) return s;
	try {
		return new URL(s).pathname || s;
	} catch {
		return s;
	}
}

/**
 * 与侧栏/选项 id 一致的路由段；`link` / `url` 可作为列表接口中的别名字段；绝对 URL 会取 pathname
 */
export function getShortcutPathFromRow(row: unknown): string | null {
	if (!row || typeof row !== 'object') return null;
	const raw = readString(row, ['web_path', 'path', 'menu_path', 'webPath', 'link', 'url']);
	if (!raw) return null;
	return maybeStripHttpPath(raw.trim()) || null;
}

/** 列表里若带 `name`/`title` 等，供以后与侧栏标题对账用 */
export function getShortcutNameFromRow(row: unknown): string | null {
	if (!row || typeof row !== 'object') return null;
	return readString(row, ['name', 'title', 'menu_name', 'menuName', 'label']);
}

/**
 * 当前页 `QuickEntryMenuOption` 上已带 i18n 后的标题，作为请求体 `name`；无匹配时退回 path，避免空串
 */
export function resolveShortcutDisplayName(
	menuPath: string,
	options: QuickEntryMenuOption[]
): string {
	const o = options.find((x) => x.id === menuPath);
	if (o?.title?.trim()) {
		return o.title.trim();
	}
	return menuPath;
}

/**
 * 后端必填的 `link`：与 `QuickEntryMenuOption.path` 一致（侧栏即路由；外链菜单若 `path` 为完整 URL 则原样上送）
 */
export function resolveShortcutLink(
	menuPath: string,
	options: QuickEntryMenuOption[]
): string {
	const o = options.find((x) => x.id === menuPath);
	const raw = (o?.path ?? o?.id ?? menuPath).trim();
	if (!raw) return menuPath;
	if (/^https?:\/\//i.test(raw)) return raw;
	return raw.startsWith('/') ? raw : `/${raw.replace(/^\//, '')}`;
}

/**
 * 与侧栏/首页卡片同源的图标 class（如 `fa fa-…`），来自 `iconClass`；无则与 `mapSidebarIconToQuickClass` 默认一致
 */
export function resolveShortcutIcon(
	menuPath: string,
	options: QuickEntryMenuOption[]
): string {
	const o = options.find((x) => x.id === menuPath);
	if (o?.iconClass?.trim()) {
		return o.iconClass.trim();
	}
	return mapSidebarIconToQuickClass(undefined);
}

/** 读列表时的图标别名字段 */
export function getShortcutIconFromRow(row: unknown): string | null {
	if (!row || typeof row !== 'object') return null;
	return readString(row, ['icon', 'icon_class', 'iconClass', 'icon_name', 'iconName']);
}

/** 读列表时若单独提供 link 与 path 分开展示，可与 `getShortcutPathFromRow` 二选一，字段别名：link / href */
export function getShortcutLinkFromRow(row: unknown): string | null {
	if (!row || typeof row !== 'object') return null;
	const raw = readString(row, ['link', 'url', 'href', 'web_path', 'path']);
	if (!raw) return null;
	return maybeStripHttpPath(raw.trim()) || null;
}

/**
 * 是否为「常用 / 高亮」槽：与 `quickEditDraft.highlightIndex` 对应；读列表时兼容 `is_active` 表示同一语义
 */
function getFrequentFromRow(row: unknown): boolean {
	if (!row || typeof row !== 'object') return false;
	const o = row as Record<string, unknown>;
	/* 若 is_active 在贵方模型中表示「全量启用」且恒为 true，请从本列表中移除 is_active，仅用 is_frequent */
	for (const k of [
		'is_frequent',
		'is_favorite',
		'is_common',
		'frequent',
		'is_hot',
		'is_active',
	] as const) {
		if (o[k] === true) return true;
	}
	return false;
}

function getSortFromRow(row: unknown): number | null {
	if (!row || typeof row !== 'object') return null;
	const v = (row as RawRow).sort;
	if (typeof v !== 'number' || Number.isNaN(v)) return null;
	if (v >= 0 && v < QUICK_ENTRY_SLOT_COUNT) return v;
	if (v >= 1 && v <= QUICK_ENTRY_SLOT_COUNT) return v - 1;
	return null;
}

function compareRows(a: unknown, b: unknown): number {
	const sa = getSortFromRow(a);
	const sb = getSortFromRow(b);
	if (sa !== null && sb !== null && sa !== sb) return sa - sb;
	const idA = (a as RawRow)?.id;
	const idB = (b as RawRow)?.id;
	const nA = idA == null ? 0 : Number(idA);
	const nB = idB == null ? 0 : Number(idB);
	if (!Number.isNaN(nA) && !Number.isNaN(nB) && nA !== nB) return nA - nB;
	return 0;
}

/**
 * 把槽位未填的路径补满（与首页本地填充思路一致，避免空槽）
 */
function ensureFiveMenuIds(
	partial: (string | null)[],
	idSet: Set<string>,
	opts: QuickEntryMenuOption[]
): string[] {
	const out = partial.map((p) => p || '');
	const used = new Set(out.filter(Boolean));
	for (let s = 0; s < QUICK_ENTRY_SLOT_COUNT; s++) {
		if (out[s]) continue;
		const fill = opts.find((o) => !used.has(o.id) && idSet.has(o.id));
		if (fill) {
			out[s] = fill.id;
			used.add(fill.id);
			continue;
		}
		for (const id of pickPreferredQuickSlotIds(opts)) {
			if (used.has(id) || !idSet.has(id)) continue;
			out[s] = id;
			used.add(id);
			break;
		}
	}
	for (let s = 0; s < QUICK_ENTRY_SLOT_COUNT; s++) {
		if (out[s]) continue;
		for (const o of opts) {
			if (used.has(o.id)) continue;
			out[s] = o.id;
			used.add(o.id);
			break;
		}
	}
	return out;
}

type Cell = { id: string | number; path: string; raw: unknown };

/**
 * 将 GET 列表（已按 sort、id 升序为最佳）解析为 5 槽 + 高亮 + 已存在记录的 id
 */
export function mapWorkbenchShortcutListToState(
	rows: unknown[],
	opts: QuickEntryMenuOption[]
): { menuIds: string[]; highlightIndex: number; recordBySlot: Map<number, { id: string | number }> } | null {
	if (!Array.isArray(rows) || !rows.length) return null;
	const idSet = new Set(opts.map((o) => o.id));
	const validRows = rows
		.map((r) => {
			if (!r || typeof r !== 'object') return null;
			const path = getShortcutPathFromRow(r);
			if (!path || !idSet.has(path)) return null;
			const id = (r as RawRow).id;
			if (id == null) return null;
			return { id, path, raw: r } as Cell;
		})
		.filter((x): x is Cell => x !== null);
	if (!validRows.length) return null;

	const rawSorted = [...validRows].sort((a, b) => compareRows(a.raw, b.raw));
	const bySlot: (Cell | null)[] = new Array(QUICK_ENTRY_SLOT_COUNT).fill(null);
	const free: Cell[] = [];

	for (const cell of rawSorted) {
		const si = getSortFromRow(cell.raw);
		if (si !== null && si >= 0 && si < QUICK_ENTRY_SLOT_COUNT && bySlot[si] === null) {
			bySlot[si] = cell;
		} else {
			free.push(cell);
		}
	}
	for (const cell of free) {
		const i = bySlot.findIndex((x) => x === null);
		if (i < 0) break;
		bySlot[i] = cell;
	}

	const pathPerSlot: (string | null)[] = new Array(QUICK_ENTRY_SLOT_COUNT).fill(null);
	const recordBySlot = new Map<number, { id: string | number }>();
	let highlightIndex = 0;
	let hasFrequent = false;
	for (let s = 0; s < QUICK_ENTRY_SLOT_COUNT; s++) {
		const c = bySlot[s];
		if (c) {
			pathPerSlot[s] = c.path;
			recordBySlot.set(s, { id: c.id });
		}
	}
	for (let s = 0; s < QUICK_ENTRY_SLOT_COUNT; s++) {
		const c = bySlot[s];
		if (c && getFrequentFromRow(c.raw) && !hasFrequent) {
			highlightIndex = s;
			hasFrequent = true;
		}
	}

	const menuIds = ensureFiveMenuIds(pathPerSlot, idSet, opts);
	if (menuIds.length !== QUICK_ENTRY_SLOT_COUNT || menuIds.some((m) => !m)) {
		return null;
	}
	return { menuIds, highlightIndex, recordBySlot };
}

function buildWritePayload(
	slotIndex: number,
	menuPath: string,
	/** 与 `quickEditDraft.highlightIndex === slotIndex` 一致，即单选「标记为常用」 */
	isPreferredSlot: boolean,
	displayName: string,
	linkValue: string,
	iconValue: string
): Record<string, unknown> {
	return {
		[WORKBENCH_SHORTCUT_WRITE.sort]: slotIndex,
		[WORKBENCH_SHORTCUT_WRITE.path]: menuPath,
		[WORKBENCH_SHORTCUT_WRITE.frequent]: isPreferredSlot,
		[WORKBENCH_SHORTCUT_WRITE.active]: isPreferredSlot,
		[WORKBENCH_SHORTCUT_WRITE.name]: displayName,
		[WORKBENCH_SHORTCUT_WRITE.link]: linkValue,
		[WORKBENCH_SHORTCUT_WRITE.icon]: iconValue,
	};
}

export async function syncQuickSlotsToServer(
	slots: string[],
	highlightIndex: number,
	recordBySlot: Map<number, { id: string | number }>,
	options: QuickEntryMenuOption[]
): Promise<void> {
	const tasks: Promise<unknown>[] = [];
	for (let s = 0; s < QUICK_ENTRY_SLOT_COUNT; s++) {
		const path = slots[s];
		if (!path) continue;
		const frequent = s === highlightIndex;
		const rec = recordBySlot.get(s);
		const name = resolveShortcutDisplayName(path, options);
		const link = resolveShortcutLink(path, options);
		const icon = resolveShortcutIcon(path, options);
		const payload = buildWritePayload(s, path, frequent, name, link, icon);
		if (rec) {
			tasks.push(workbenchApi.patchUserWorkbenchShortcut(rec.id, payload));
		} else {
			tasks.push(workbenchApi.createUserWorkbenchShortcut(payload));
		}
	}
	await Promise.all(tasks);
}

/** 与 map 规则一致，从当前列表重算每槽的 id，保存后调用以同步 PATCH 目标 */
export function buildRecordBySlotFromList(
	list: unknown[],
	opts: QuickEntryMenuOption[]
): Map<number, { id: string | number }> {
	const m = new Map<number, { id: string | number }>();
	const st = mapWorkbenchShortcutListToState(list, opts);
	if (st) {
		return st.recordBySlot;
	}
	return m;
}
