import { BASE_HOST } from '@wispplace/constants'

const RESERVED_HANDLES = new Set([
	'www',
	'api',
	'admin',
	'static',
	'public',
	'preview',
	'slingshot',
	'plc',
	'constellation',
	'cdn',
	'pds',
	'staging',
	'auth',
])

const RESERVED_CUSTOM_DOMAINS = new Set([
	'localhost',
	'example.com',
	'example.org',
	'example.net',
	'test',
	'invalid',
	'local',
])

const RESERVED_CUSTOM_PATTERNS = [/^(?:10|127|172\.(?:1[6-9]|2[0-9]|3[01])|192\.168)\./, /^(?:\d{1,3}\.){3}\d{1,3}$/]

const CUSTOM_DOMAIN_PATTERN = /^(?:[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,}$/

export const normalizeDomain = (domain: string): string => {
	return domain.trim().toLowerCase().replace(/\.$/, '')
}

export const isValidHandle = (handle: string): boolean => {
	const normalized = handle.trim().toLowerCase()

	if (normalized.length < 3 || normalized.length > 63) return false
	if (!/^[a-z0-9-]+$/.test(normalized)) return false
	if (normalized.startsWith('-') || normalized.endsWith('-')) return false
	if (normalized.includes('--')) return false
	if (RESERVED_HANDLES.has(normalized)) return false

	return true
}

export const toDomain = (handle: string): string => `${handle.toLowerCase()}.${BASE_HOST}`

export const extractWispHandle = (domain: string): string | null => {
	const normalized = normalizeDomain(domain)
	const suffix = `.${BASE_HOST}`

	if (!normalized.endsWith(suffix)) {
		return null
	}

	const handle = normalized.slice(0, -suffix.length)
	if (handle.length === 0 || handle.includes('.')) {
		return null
	}

	return handle
}

export const validateCustomDomain = (domain: string): string | null => {
	const normalized = normalizeDomain(domain)

	if (normalized.length < 3 || normalized.length > 253) {
		return 'domain must be 3-253 characters'
	}

	if (!CUSTOM_DOMAIN_PATTERN.test(normalized)) {
		return 'invalid domain format'
	}

	const labels = normalized.split('.')
	for (const label of labels) {
		if (label.length === 0 || label.length > 63) {
			return 'domain labels must be 1-63 characters'
		}
		if (label.startsWith('-') || label.endsWith('-')) {
			return 'domain labels cannot start or end with hyphen'
		}
	}

	const tld = labels[labels.length - 1]
	if (tld.length < 2 || /^\d+$/.test(tld)) {
		return 'tld must be at least 2 characters and not all numeric'
	}

	if (!/^[a-z0-9.-]+$/.test(normalized)) {
		return 'domain must use ascii alphanumeric characters, dots, and hyphens'
	}

	if (RESERVED_CUSTOM_DOMAINS.has(normalized)) {
		return 'reserved or blocked domain'
	}

	for (const pattern of RESERVED_CUSTOM_PATTERNS) {
		if (pattern.test(normalized)) {
			return 'ip addresses are not allowed'
		}
	}

	return null
}
