import { Request, Response, NextFunction } from 'express'
import { validate } from 'super-easy-validator'
import helpers from '../../../utils/helpers'

const startTimeRegex = /^(0?[1-9]|1[0-2]):[0-5][0-9] (AM|PM)$/

async function getEvents(req: Request, res: Response, next: NextFunction) {
	await helpers.runApi(res, () => {
		const rules = {
			limit: 'optional|string|natural',
			page: 'optional|string|natural'
		}
		const { errors } = validate(rules as any, req.query)
		if (errors) {
			return res.status(400).json({ message: errors[0] })
		}
		return next()
	})
}

async function checkEventId(req: Request, res: Response, next: NextFunction) {
	await helpers.runApi(res, () => {
		const rules = {
			id: 'mongoid'
		}

		const { errors } = validate(rules as any, req.params)
		if (errors) {
			return res.status(400).json({ message: errors[0] })
		}

		return next()
	})
}

async function postEvent(req: Request, res: Response, next: NextFunction) {
	await helpers.runApi(res, () => {
		// form data may send single community id as string or JSON array
		if (typeof req.body.communities === 'string') {
			if (req.body.communities.trim().startsWith('[')) {
				try {
					req.body.communities = JSON.parse(req.body.communities)
				} catch {
					req.body.communities = []
				}
			} else {
				req.body.communities = req.body.communities.trim() ? [req.body.communities.trim()] : []
			}
		}
		const rules = {
			user: 'string|min:1|max:50',
			title: 'string|min:5|max:200',
			description: 'string|min:10|max:5000',
			date: 'dateonly',
			time: 'string',
			locationString: 'string|min:3|max:180|field:location',
			latitude: 'string|number|min:-90|max:90',
			longitude: 'string|number|min:-180|max:180',
			category: 'optional|string|min:2|max:20',
			url: 'optional|url',
			communities: 'optional|array|arrayof:mongoid',
			joiningCost: 'optional|string|number|positive',
			membersLimit: 'optional|string|natural',
			featured: 'optional|string|boolean'
		}

		const { errors } = validate(rules as any, req.body)
		if (errors) {
			return res.status(400).json({ message: errors[0] })
		}

		if (!startTimeRegex.test(req.body.time)) {
			return res.status(400).json({ message: 'time is invalid' })
		}

		return next()
	})
}

async function patchEvent(req: Request, res: Response, next: NextFunction) {
	await helpers.runApi(res, () => {
		// form data may send single community id as string or JSON array
		if (typeof req.body.communities === 'string') {
			if (req.body.communities.trim().startsWith('[')) {
				try {
					req.body.communities = JSON.parse(req.body.communities)
				} catch {
					req.body.communities = []
				}
			} else {
				req.body.communities = req.body.communities.trim() ? [req.body.communities.trim()] : []
			}
		}
		const rules = {
			id: 'mongoid',
			title: 'optional|string|min:5|max:200',
			description: 'optional|string|min:10|max:5000',
			date: 'optional|dateonly',
			time: 'optional|string',
			locationString: 'optional|string|min:3|max:180|field:location',
			latitude: 'optional|string|number|min:-90|max:90',
			longitude: 'optional|string|number|min:-180|max:180',
			category: 'optional|string|min:2|max:20',
			url: 'optional|string',
			communities: 'optional|array|arrayof:mongoid',
			joiningCost: 'optional|string|number|positive',
			membersLimit: 'optional|string|natural',
			featured: 'optional|string|boolean'
		}

		const { errors } = validate(rules as any, { ...req.body, ...req.params })
		if (errors) {
			return res.status(400).json({ message: errors[0] })
		}

		if (req.body.url) {
			const urlRules = {
				url: 'url'
			}
			const { errors: urlErrors } = validate(urlRules as any, req.body)
			if (urlErrors) {
				return res.status(400).json({ message: urlErrors[0] })
			}
		}

		const { date, time, latitude, longitude } = req.body
		if ((latitude && !longitude) || (longitude && !latitude)) {
			return res.status(400).json({ message: 'both latitude & longitude are required' })
		}
		if ((date && !time) || (time && !date)) {
			return res.status(400).json({ message: 'both date & time are required' })
		}
		if (time && !startTimeRegex.test(time)) {
			return res.status(400).json({ message: 'time is invalid' })
		}

		return next()
	})
}

const validations = {
	getEvents,
	checkEventId,
	postEvent,
	patchEvent
}

export default validations
