const ALLOWED_EXTENSIONS = ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt', 'md', 'csv']
const MAX_FILE_SIZE = 50 * 1024 * 1024
const BACKEND_TIMEZONE_OFFSET_MINUTES = 8 * 60
const SESSION_EXPIRES_AT_PATTERN = /^(\d{4})-(\d{2})-(\d{2})([ T])(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?(?:(Z)|([+-])(\d{2}):?(\d{2}))?$/

function validateEnterpriseWebsite(value) {
	const normalized = String(value || '').trim()
	if (!normalized) return '请输入企业官网，无官网请填写“无”'
	if (normalized.length > 500) return '企业官网不能超过500个字符'
	if (normalized === '无') return ''
	if (!/^https?:\/\/[^/\s?#]+(?:[/?#][^\s]*)?$/i.test(normalized)) return '请输入以http://或https://开头的企业官网'
	return ''
}

function validateBackgroundFile(file) {
	if (!file || !file.name || !file.size) return '请选择非空文件'
	if (file.name.length > 255) return '文件名不能超过255个字符'
	const ext = file.name.includes('.') ? file.name.split('.').pop().toLowerCase() : ''
	if (!ALLOWED_EXTENSIONS.includes(ext)) return '文件类型不支持'
	if (file.size > MAX_FILE_SIZE) return '单个文件不能超过50MB'
	return ''
}

function parseSessionExpiresAt(value) {
	const matched = SESSION_EXPIRES_AT_PATTERN.exec(String(value || '').trim())
	if (!matched) return NaN
	const year = Number(matched[1])
	const month = Number(matched[2])
	const day = Number(matched[3])
	const separator = matched[4]
	const hour = Number(matched[5])
	const minute = Number(matched[6])
	const second = Number(matched[7])
	const millisecond = Number((matched[8] || '').padEnd(3, '0'))
	if (year < 1000 || month < 1 || month > 12 || day < 1 || day > 31
		|| hour > 23 || minute > 59 || second > 59) return NaN

	const hasExplicitTimezone = Boolean(matched[9] || matched[10])
	if (separator === 'T' && !hasExplicitTimezone) return NaN
	if (separator === ' ' && hasExplicitTimezone) return NaN

	const localWallClock = Date.UTC(year, month - 1, day, hour, minute, second, millisecond)
	const normalized = new Date(localWallClock)
	if (normalized.getUTCFullYear() !== year || normalized.getUTCMonth() !== month - 1
		|| normalized.getUTCDate() !== day || normalized.getUTCHours() !== hour
		|| normalized.getUTCMinutes() !== minute || normalized.getUTCSeconds() !== second) return NaN

	let offsetMinutes = BACKEND_TIMEZONE_OFFSET_MINUTES
	if (matched[9] === 'Z') {
		offsetMinutes = 0
	} else if (matched[10]) {
		const offsetHour = Number(matched[11])
		const offsetMinute = Number(matched[12])
		if (offsetHour > 23 || offsetMinute > 59) return NaN
		offsetMinutes = (offsetHour * 60 + offsetMinute) * (matched[10] === '+' ? 1 : -1)
	}
	return localWallClock - offsetMinutes * 60 * 1000
}

function getSessionRemainingSeconds(expiresAt, now = Date.now()) {
	const expiresAtTime = parseSessionExpiresAt(expiresAt)
	if (!Number.isFinite(expiresAtTime)) return 0
	return Math.max(0, Math.ceil((expiresAtTime - now) / 1000))
}

function createBackgroundQueueItem(file, id) {
	const selectedFile = file || {}
	const validationError = validateBackgroundFile(selectedFile)
	return {
		id,
		name: selectedFile.name || '',
		path: selectedFile.path || '',
		size: selectedFile.size || 0,
		progress: 0,
		status: validationError ? 'failed' : 'pending',
		error: validationError,
		validationError
	}
}

function getUploadableBackgroundFiles(queue) {
	return Array.isArray(queue)
		? queue.filter(file => file.status === 'pending'
			|| (file.status === 'failed' && !file.validationError))
		: []
}

function createTeamSubmitPayload(teamInfo) {
	const payload = Object.assign({}, teamInfo || {})
	payload.enterpriseWebsite = String(payload.enterpriseWebsite || '').trim()
	delete payload.source
	delete payload.coachId
	delete payload.uploaderId
	return payload
}

function sortPayloadValue(value) {
	if (Array.isArray(value)) return value.map(sortPayloadValue)
	if (!value || typeof value !== 'object') return value
	return Object.keys(value).sort().reduce((result, key) => {
		result[key] = sortPayloadValue(value[key])
		return result
	}, {})
}

function createTeamPayloadSnapshot(teamInfo) {
	return JSON.stringify(sortPayloadValue(createTeamSubmitPayload(teamInfo)))
}

function createEmptyTextPreviewState() {
	return { visible: false, fileName: '', content: '', truncated: false }
}

function createTextPreviewState(result, fallbackFileName) {
	const preview = result || {}
	return {
		visible: true,
		fileName: preview.fileName || fallbackFileName || '文本预览',
		content: String(preview.content === undefined || preview.content === null ? '' : preview.content),
		truncated: Boolean(preview.truncated)
	}
}

function createTeamCreationState() {
	return {
		createdTeamId: '',
		submitting: false,
		stage: 'idle',
		completed: false,
		teamPayloadSnapshot: '',
		backgroundSurveyId: '',
		backgroundSurveyStatus: 'DRAFT',
		teamQuestionnaireId: '',
		publishResult: null,
		resumeStage: ''
	}
}

function beginTeamSubmission(state) {
	if (!state || state.submitting || state.completed) return false
	state.submitting = true
	return true
}

function rememberCreatedTeam(state, teamId) {
	if (!state) return ''
	if (!state.createdTeamId && teamId) state.createdTeamId = teamId
	return state.createdTeamId
}

function setTeamSubmissionStage(state, stage) {
	if (state) state.stage = stage || 'idle'
}

function finishTeamSubmission(state, completed = false) {
	if (!state) return
	state.submitting = false
	state.completed = state.completed || completed
	if (completed) state.stage = 'complete'
}

function hasUnresolvedBackgroundFiles(queue) {
	return Array.isArray(queue) && queue.some(item => item.status === 'pending'
		|| item.status === 'uploading'
		|| (item.status === 'failed' && !item.validationError))
}

module.exports = {
	ALLOWED_EXTENSIONS,
	MAX_FILE_SIZE,
	validateEnterpriseWebsite,
	validateBackgroundFile,
	parseSessionExpiresAt,
	getSessionRemainingSeconds,
	createBackgroundQueueItem,
	getUploadableBackgroundFiles,
	createTeamSubmitPayload,
	createTeamPayloadSnapshot,
	createEmptyTextPreviewState,
	createTextPreviewState,
	createTeamCreationState,
	beginTeamSubmission,
	rememberCreatedTeam,
	setTeamSubmissionStage,
	finishTeamSubmission,
	hasUnresolvedBackgroundFiles
}
