import dayjs from 'dayjs';

/** 与流程管理里「流程类型」一致：设备借用申请 */
export const WORKFLOW_TYPE_EQUIPMENT_BORROW = '0';

/** 借用类型：与 WorkflowDialog 中 checkbox 值一致 */
export const BORROW_TYPE_SPECIAL = '2';

export type WorkflowListItem = Record<string, any>;

export interface SpecialBorrowMatchInput {
	borrow_type: number;
	borrower_type: number;
	team_type: number;
	expected_start_time?: string | null;
	expected_end_time?: string | null;
	/** 应用用户借用时，对应 app_user 的 user_type（0 学生 1 教师 3 学院领导等） */
	app_user_type?: number | null;
}

function getConditionBlock(w: WorkflowListItem) {
	const tc = w.trigger_conditions || {};
	const dr0 =
		Array.isArray(w.duration_rules) && w.duration_rules[0] ? w.duration_rules[0] : {};
	return {
		min_days: dr0.min_days ?? tc.min_days ?? null,
		max_days: dr0.max_days ?? tc.max_days ?? null,
		borrow_types: (dr0.borrow_types ?? tc.borrow_types ?? []).map((x: any) => String(x)),
		team_type: (tc.team_type ?? []).map((x: any) => String(x)),
		user_types: (tc.user_types ?? []).map((x: any) => String(x)),
	};
}

/** 预计开始、结束日之间的借用天数（含起止日，与业务上「借 N 天」常见口径一致） */
export function getBorrowInclusiveDays(input: SpecialBorrowMatchInput): number | null {
	const end = input.expected_end_time;
	if (end == null || String(end).trim() === '') return null;
	const startRaw =
		input.expected_start_time && String(input.expected_start_time).trim() !== ''
			? String(input.expected_start_time)
			: dayjs().format('YYYY-MM-DD');
	const start = dayjs(startRaw).startOf('day');
	const endD = dayjs(end).startOf('day');
	if (!start.isValid() || !endD.isValid()) return null;
	const d = endD.diff(start, 'day') + 1;
	return d >= 1 ? d : null;
}

/** 申请人角色与流程条件里 user_types（教师/学生/非本院师生）对齐 */
export function applicantUserTypesForMatch(input: SpecialBorrowMatchInput): string[] {
	if (input.borrower_type === 2) return ['external'];
	if (input.borrower_type === 0) return ['teacher'];
	if (input.borrower_type === 1) {
		const ut = input.app_user_type;
		if (ut === 0) return ['student'];
		if (ut === 1 || ut === 3) return ['teacher'];
		return [];
	}
	return [];
}

function daysInRange(days: number, minDays: number | null, maxDays: number | null): boolean {
	if (minDays != null && Number.isFinite(Number(minDays)) && days < Number(minDays)) {
		return false;
	}
	if (maxDays != null && Number.isFinite(Number(maxDays)) && days > Number(maxDays)) {
		return false;
	}
	return true;
}

function hasUserTypeOverlap(condTypes: string[], applicant: string[]): boolean {
	if (!condTypes.length) return true;
	if (!applicant.length) return false;
	const set = new Set(condTypes);
	return applicant.some((t) => set.has(t));
}

function specificityScore(cond: ReturnType<typeof getConditionBlock>): number {
	let s = 0;
	if (cond.borrow_types.length) s += 2;
	if (cond.team_type.length) s += 1;
	if (cond.user_types.length) s += 1;
	if (cond.min_days != null && Number(cond.min_days) > 0) s += 1;
	if (cond.max_days != null) s += 1;
	return s;
}

/**
 * 在已拉取的流程列表中，为当前特殊借用单选出唯一 workflow id。
 * 规则与流程配置一致：启用、设备借用类型、借用类型含特殊借用、天数区间、团队方式、用户角色等。
 */
export function pickWorkflowIdForSpecialBorrow(
	workflows: WorkflowListItem[],
	input: SpecialBorrowMatchInput
): number | null {
	const days = getBorrowInclusiveDays(input);
	if (days == null) return null;

	const applicantRoles = applicantUserTypesForMatch(input);
	const teamStr = String(input.team_type);

	const candidates: { id: number; score: number }[] = [];

	for (const w of workflows) {
		if (w.is_active === false) continue;
		if (String(w.workflow_type ?? '') !== WORKFLOW_TYPE_EQUIPMENT_BORROW) continue;

		const cond = getConditionBlock(w);
		if (cond.borrow_types.length && !cond.borrow_types.includes(BORROW_TYPE_SPECIAL)) {
			continue;
		}
		if (cond.team_type.length && !cond.team_type.includes(teamStr)) {
			continue;
		}
		if (!hasUserTypeOverlap(cond.user_types, applicantRoles)) {
			continue;
		}
		if (!daysInRange(days, cond.min_days, cond.max_days)) {
			continue;
		}
		const id = Number(w.id);
		if (!Number.isFinite(id)) continue;
		candidates.push({ id, score: specificityScore(cond) });
	}

	if (!candidates.length) return null;

	candidates.sort((a, b) => {
		if (b.score !== a.score) return b.score - a.score;
		return a.id - b.id;
	});
	return candidates[0].id;
}

export function findWorkflowNameById(
	workflows: WorkflowListItem[],
	id: number | null
): string {
	if (id == null) return '';
	const w = workflows.find((x) => Number(x.id) === Number(id));
	return w?.name ? String(w.name) : '';
}
