const crypto = require('crypto')
const express = require('express')
const db = require('../include/db')
const bot = require('./bot')
const fs = require('fs')

const app = express.Router()

const sessions = {}
const cache = {
	// email -> code
	register: {},  
	upgrade: {},
	recovery: {},
	'change-password': {},
	'change-email': {},
	'change-email2': {}
}

function checkEmail(email){
	return String(email)
		.toLowerCase()
		.match(/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/)
}

function sendEmail(email, subject, message) {
	console.log(`${email} --> ${subject}: ${message}`)
}

function checkPassword(password) {
	return password.length >= 8
}

app.use((req, res, next) => {
	const public = [
		'/auth/email',
		'/auth/telegram',
		'/auth/email/register',
		'/auth/email/recovery',
		'/auth/logout'
	]

	if (public.includes(req.path))
		return next()

	const asid = req.query.asid || req.cookies.asid
	req.session = sessions[asid]
	if (!req.session) 
		throw Error('ACCESS_DENIED::401')

	res.locals.customer_id = req.session.customer_id
	next()
})

// AUTH
function createSession(req, res, customer_id) {
	if (!customer_id)
		throw Error('AUTH_ERROR::500')

	res.locals.customer_id = customer_id
	const asid = crypto.randomBytes(64).toString('hex')
	req.session = sessions[asid] = {asid, customer_id }
	res.setHeader('Set-Cookie', [`asid=${asid};httpOnly;path=/api/admin`])	
}

app.post('/auth/email', (req, res, next) => {
	res.locals.email = req.body?.email
	res.locals.password = req.body?.password
	 
	const customer_id = db
		.prepare(`select id from customers  where email = :email and password is not null and password = :password `)
		.pluck(true)
		.get(res.locals)

	if (!customer_id) 
		throw Error('AUTH_ERROR::401')

	createSession(req, res, customer_id)
	res.status(200).json({success: true})
})

app.post('/auth/telegram', (req, res, next) => {
	let customer_id = db
		.prepare(`select id from customers where telegram_id = :telegram_id`)
		.pluck(true)
		.get(res.locals) || db
		.prepare(`insert into customers (telegram_id) values (:telegram_id) returning id`)
		.pluck(true)
		.get(res.locals)		

	createSession(req, res, customer_id)
	res.status(200).json({success: true})
})

/*
	Регистрация нового клиента/Перевод авторизации с TG на email выполняется за ТРИ последовательных вызова
	1. Отравляется email. Если email корректный и уже неиспользуется, то сервер возвращает ОК и на указанный email отправляется код.
	2. Отправляется email + код из письма. Если указан корректный код, то сервер отвечает ОК. 
	3. Отправляется email + код из письма + желаемый пароль. Если все ОК, то сервер создает учетную запись и возвращает ОК.
*/
app.post('/auth/email/:action(register|upgrade)', (req, res, next) => {
	const email = String(req.body.email ?? '').trim()
	const code = String(req.body.code ?? '').trim()
	const password = String(req.body.password ?? '').trim()
	const action = req.params.action

	const stepNo = email && !code ? 1 : email && code && !password ? 2 : email && code && password ? 3 : -1
	if (stepNo == -1)
		throw Error('BAD_STEP::400')	

	if (stepNo == 1) {
		if (!checkEmail(email)) 
			throw Error('INCORRECT_EMAIL::400')

		const customer_id = db
			.prepare('select id from customers where email = :email')
			.pluck(true)
			.get({email}) 

		if (customer_id) 	
			throw Error('USED_EMAIL::400')

		const code = Math.random().toString().substr(2, 4) 
		cache[action][email] = code
		sendEmail(email, action.toUpperCase(), `${email} => ${code}`)
	}

	if (stepNo == 2) {
		if (cache[action][email] != code)
			throw Error('INCORRECT_CODE::400')
	}

	if (stepNo == 3) {
		if (!checkPassword(password))
			throw Error('INCORRECT_PASSWORD::400')

		const query = action == 'register' ? 'insert into customers (email, password) values (:email, :password)' :
			'update customers set email = :email, password = :password, telegram_id = null where id = :id'
		db.prepare(query).run({email, password, id: res.locals.customer_id}) 

		delete cache[action][email]
	}

	res.status(200).json({success: true})			
})


/*
	Смена email выполняется за ПЯТЬ последовательных вызовов
	1. Отравляется пустой закпрос. Сервер на email пользователя из базы отправляет код.
	2. Отправляется код из письма. Если указан корректный код, то сервер отвечает ОК. 
	3. Отправляется код из письма + новый email. Сервер отправляет код2 на новый email.
	4. Отправлются оба кода и новый email. Если коды проходят проверку, то сервер отвечает ОК. 
	5. Отправлются оба кода, новые email и password. Если они проходят проверку, то сервер меняет email и пароль пользователя на новый и возвращает ОК.
*/
app.post('/auth/email/change-email', (req, res, next) => {
	const email2 = String(req.body.email ?? '').trim()
	const code = String(req.body.code ?? '').trim()
	const code2 = String(req.body.code2 ?? '').trim()
	const password = String(req.body.password ?? '').trim()

	const email = db
		.prepare('select email from customers where id = :customer_id')
		.pluck(true)
		.get(res.locals)

	const stepNo = !code ? 1 : code && !email2 ? 2 : code && email2 && !code2 ? 3 : code && email2 && code2 && !password ? 4 : code && email2 && code2 && password ? 5 : -1
	if (stepNo == -1)
		throw Error('BAD_STEP::400')

	if (stepNo == 1) {
		const code = Math.random().toString().substr(2, 4) 
		cache['change-email'][email] = code
		sendEmail(email, 'CHANGE-EMAIL', `${email} => ${code}`) 
	}

	if (stepNo == 2) {
		if (cache['change-email'][email] != code)
			throw Error('INCORRECT_CODE::400')
	}

	if (stepNo == 3) {
		if (!checkEmail(email2)) 
			throw Error('INCORRECT_EMAIL::400')

		const code2 = Math.random().toString().substr(2, 4)
		cache['change-email2'][email2] = code2
		sendEmail(email2, 'CHANGE-EMAIL2', `${email2} => ${code2}`) 
	}

	if (stepNo == 4) {
		if (cache['change-email'][email] != code || cache['change-email2'][email2] != code2)
			throw Error('INCORRECT_CODE::400')
	}

	if (stepNo == 5) {
		if (!checkPassword(password)) 
			throw Error('INCORRECT_PASSWORD::400')

		res.locals.email = email2
		res.locals.password = password

		const info = db
			.prepare('update customers set email = :email, password = :password where id = :customer_id')
			.run(res.locals) 

		if (info.changes == 0) 
			throw Error('BAD_REQUEST::400')

		delete cache['change-email'][email]
		delete cache['change-email2'][email2]
	}

	res.status(200).json({success: true})
})

/*
	Смена пароля/восстановление доступа выполняется за ТРИ последовательных вызова
	1. Отравляется пустой закпрос для смены запоса и email, в случае восстановления доступа. Сервер на email отправляет код.
	2. Отправляется email + код из письма. Если указан корректный код, то сервер отвечает ОК. 
	3. Отправляется email + код из письма + новый пароль. Сервер изменяет пароль и возвращает ОК.
*/
app.post('/auth/email/:action(change-password|recovery)', (req, res, next) => {
	const code = String(req.body.code ?? '').trim()
	const password = String(req.body.password ?? '').trim()
	const action = req.params.action

	const email = action == 'change-password' ? db
		.prepare('select email from customers where id = :customer_id')
		.pluck(true)
		.get(res.locals) :
		String(req.body.email ?? '').trim()

	const stepNo = action == 'change-password' ? 
		(!code && !password ? 1 : code && !password ? 2 : code && password ? 3 : -1) : 
		(!email && !code && !password ? 1 : email && code && !password ? 2 : email && code && password ? 3 : -1)
	if (stepNo == -1)
		throw Error('BAD_STEP::400')

	if (stepNo == 1) {
		if (!checkEmail(email)) 
			throw Error('INCORRECT_EMAIL::400')

		const code = Math.random().toString().substr(2, 4) 
		cache[action][email] = code
		sendEmail(email, action.toUpperCase(), `${email} => ${code}`)
	} 

	if (stepNo == 2) {
		if (cache[action][email] != code)
			throw Error('INCORRECT_CODE::400')
	}

	if (stepNo == 3) {
		if (cache[action][email] != code)
			throw Error('INCORRECT_CODE::400')

		if (!checkPassword(password))
			throw Error('INCORRECT_PASSWORD::400')

		const info = db
			.prepare('update customers set password = :password where email = :email')
			.run({ email, password }) 

		if (info.changes == 0) 
			throw Error('BAD_REQUEST::400')

		delete cache[action][email]	
	}

	res.status(200).json({success: true})
})

app.get('/auth/logout', (req, res, next) => {
	if (req.session?.asid)
		delete sessions[req.session.asid]

	res.setHeader('Set-Cookie', [`asid=; expired; httpOnly;path=/api/admin`])
	res.status(200).json({success: true})
})

// CUSTOMER
app.get('/customer/profile', (req, res, next) => {
	res.locals.time = Math.floor(Date.now() / 1000) 
	const row = db
		.prepare(`
			select id, name, email, plan, 
				coalesce(json_balance, '{}') json_balance, coalesce(json_company, '{}') json_company, 
				upload_chat_id, generate_key(-id, :time) upload_token
			from customers 
			where id = :customer_id
		`)
		.get(res.locals) 

	if (row?.upload_chat_id) {
		row.upload_chat = db
			.prepare(`select id, name, telegram_id from chats where id = :chat_id and project_id is null`)
			.safeIntegers(true)
			.get({ chat_id: row.upload_chat_id})  
		delete row.upload_chat_id
	}

	for (const key in row) {
		if (key.startsWith('json_')) {
			row[key.substr(5)] = JSON.parse(row[key])
			delete row[key]
		}
	}
	
	res.status(200).json({success: true, data: row})
})

app.put('/customer/profile', (req, res, next) => {
	if (req.body.company instanceof Object) 
		req.body.json_company = JSON.stringify(req.body.company) 
	else
		delete req.body?.json_company

	const info = db
		.prepareUpdate(
			'customers', 
			['name', 'password', 'json_company'], 
			req.body, 
			['id'])
		.run(Object.assign({}, req.body, {id: req.session.customer_id}))
	
	if (info.changes == 0) 
		throw Error('NOT_FOUND::404')

	res.status(200).json({success: true})
})

app.get('/customer/settings', (req, res, next) => {
	const row = db
		.prepare(`select coalesce(json_settings, '{}') from customers where id = :customer_id`)
		.pluck(true)
		.get(res.locals)
	
	res.status(200).json({success: true, data: JSON.parse(row)})
})

app.put('/customer/settings', (req, res, next) => {
	res.locals.json_settings = JSON.stringify(req.body || {})

	db
		.prepare(`update customers set json_settings = :json_settings where id = :customer_id`)
		.run(res.locals)
	
	res.status(200).json({success: true})
})

// PROJECT
function getProject(id, customer_id) {
	const row = db
		.prepare(`
			select id, name, description, logo, is_logo_bg, company_id, is_archived, 
				(select count(*) from chats where project_id = p.id) chat_count, 
				(select count(distinct user_id) from chat_users where chat_id in (select id from chats where project_id = p.id)) user_count
			  from projects p
			 where customer_id = :customer_id and p.id = :id
			 order by name
		`)
		.get({id, customer_id})

	if (!row)
		throw Error('NOT_FOUND::404')

	row.is_archived = Boolean(row.is_archived)
	row.is_logo_bg = Boolean(row.is_logo_bg)

	return row
}

app.get('/project', (req, res, next) => {
	const data = db
		.prepare(`
			select id, name, description, logo, is_logo_bg, company_id, is_archived, 
				(select count(*) from chats where project_id = p.id) chat_count, 
				(select count(distinct user_id) from chat_users where chat_id in (select id from chats where project_id = p.id)) user_count
			  from projects p
			 where customer_id = :customer_id 
			 order by name
		`)
		.all(res.locals)

	data.forEach(row => {
		row.is_archived = Boolean(row.is_archived)
		row.is_logo_bg = Boolean(row.is_logo_bg)		
	})

	res.status(200).json({success: true, data})
})

app.post('/project', (req, res, next) => {
	res.locals.name = req.body?.name
	res.locals.description = req.body?.description
	res.locals.logo = req.body?.logo
	res.locals.is_logo_bg = 'is_logo_bg' in req.body ? +req.body.is_logo_bg : undefined

	res.locals.project_id = db
		.prepare(`
			insert into projects (customer_id, name, description, logo, is_logo_bg) 
			values (:customer_id, :name, :description, :logo, :is_logo_bg) 
			returning id
		`)
		.pluck(true)
		.get(res.locals)
	
	const json_company = db
		.prepare(`select coalesce(json_company, '{}') from customers where id = :customer_id`)
		.pluck(true)
		.get(res.locals)

	res.locals.company_id = addCompany(Object.assign({
		name: 'My Company',
		address: null,
		email: null,
		phone: null,
		site: null,
		description: null,
		logo: null
	}, JSON.parse(json_company), {project_id: res.locals.project_id}))

	db
		.prepare(`update projects set company_id = :company_id where id = :project_id`)
		.run(res.locals)

	const data = getProject(res.locals.project_id, res.locals.customer_id)
	res.status(200).json({success: true, data})
})

app.use ('(/project/:pid(\\d+)/*|/project/:pid(\\d+))', (req, res, next) => {
	res.locals.project_id = parseInt(req.params.pid) 

	const row = db
		.prepare('select 1 from projects where id = :project_id and customer_id = :customer_id and is_archived <> 1')
		.get(res.locals)

	if (!row)
		throw Error('ACCESS_DENIED::401')

	next()
})

app.get('/project/:pid(\\d+)', (req, res, next) => {
	const data = getProject(req.params.pid, res.locals.customer_id)
	res.status(200).json({success: true, data})
})

app.put('/project/:pid(\\d+)', (req, res, next) => {
	res.locals.id = req.params.pid
	res.locals.name = req.body?.name
	res.locals.description = req.body?.description
	res.locals.logo = req.body?.logo
	res.locals.is_logo_bg = 'is_logo_bg' in req.body ? +req.body.is_logo_bg : undefined

	const info = db
		.prepareUpdate(
			'projects', 
			['name', 'description', 'logo', 'is_logo_bg'], 
			res.locals, 
			['id', 'customer_id'])
		.run(res.locals)
	
	if (info.changes == 0)
		throw Error('NOT_FOUND::404')

	const data = getProject(req.params.pid, res.locals.customer_id)
	res.status(200).json({success: true, data})
})

app.put('/project/:pid(\\d+)/:action(archive|restore)', async (req, res, next) => {
	res.locals.id = req.params.pid
	res.locals.is_archived = +(req.params.action == 'archive')

	const info = db
		.prepare(`
			update projects 
			set is_archived = :is_archived 
			where id = :id and customer_id = :customer_id and coalesce(is_archived, 0) = not :is_archived
		`)
		.run(res.locals)

	if (info.changes == 0)
		throw Error('BAD_REQUEST::400')

	const chatIds = db
		.prepare(`select id from chats where project_id = :id`)
		.pluck(true)
		.all(res.locals)

	for (const chatId of chatIds) {
		await bot.sendMessage(chatId, res.locals.is_archived  ? 'Проект помещен в архив. Отслеживание сообщений прекращено.' : 'Проект восстановлен из архива.')
	}
	
	const data = getProject(req.params.pid, res.locals.customer_id)
	res.status(200).json({success: true, data})
})

// USER
function getUser(id, project_id) {
	const row = db
		.prepare(`
			select u.id, u.telegram_id, u.firstname, u.lastname, u.username, u.photo,
			       ud.fullname, ud.email, ud.phone, ud.role, ud.department, ud.is_blocked,
				   (select company_id from company_users where user_id = :id) company_id,
				   (select json_group_array(chat_id) from chat_users where user_id = :id and chat_id in (select id from chats where project_id = :project_id)) chats
			  from users u
			       left join user_details ud on u.id = ud.user_id and ud.project_id = :project_id
			 where id = :id
		`)
		.safeIntegers(true)
		.get({id, project_id}) 

	if (!row)
		throw Error('NOT_FOUND::404')

	row.chats = JSON.parse(row.chats || '[]')
	row.is_blocked = Boolean(row.is_blocked)
	
	return row
}

app.get('/project/:pid(\\d+)/user', (req, res, next) => {
	const data = db
		.prepare(`
			select u.id, u.telegram_id, u.firstname, u.lastname, u.username, u.photo,
			       ud.fullname, ud.email, ud.phone, ud.role, ud.department, ud.is_blocked,
			        (select company_id from company_users where user_id = u.id) company_id
			  from users u
			       left join user_details ud on u.id = ud.user_id and ud.project_id = :project_id
			 where id in (
				select user_id 
				from chat_users 
				where chat_id in (select id from chats where project_id = :project_id)
				)
		`)
		.safeIntegers(true)
		.all(res.locals) 

		data.forEach(row => {
			row.is_blocked = Boolean(row.is_blocked)
		})		

	res.status(200).json({success: true, data})
})

app.get('/project/:pid(\\d+)/user/:uid(\\d+)', (req, res, next) => {
	const data = getUser(req.params.uid, req.params.pid)
	res.status(200).json({success: true, data})
})

app.put('/project/:pid(\\d+)/user/:uid(\\d+)', (req, res, next) => {
	res.locals.user_id = parseInt(req.params.uid)
	
	res.locals.fullname = req.body?.fullname
	res.locals.email = req.body?.email
	res.locals.phone = req.body?.phone
	res.locals.role = req.body?.role
	res.locals.department = req.body?.department
	res.locals.is_blocked = 'is_blocked' in req.body ? +req.body.is_blocked : undefined

	const info = db
		.prepareUpsert('user_details', 
			['fullname', 'email', 'phone', 'role', 'department', 'is_blocked'], 
			res.locals, 
			['user_id', 'project_id']
		) 
		.run(res.locals) 			
	
	const data = getUser(req.params.uid, req.params.pid)
	res.status(200).json({success: true, data})
})

app.get('/project/:pid(\\d+)/token', (req, res, next) => {
	res.locals.time = Math.floor(Date.now() / 1000)

	const key = db
		.prepare('select generate_key(id, :time) from projects where id = :project_id and customer_id = :customer_id')
		.pluck(true)
		.get(res.locals)

	if (!key)
		throw Error('NOT_FOUND::404')

	res.status(200).json({success: true, data: key})		  
})

// COMPANY
function addCompany(data) {
	return db
		.prepare(`
			insert into companies (project_id, name, address, email, phone, site, description, logo) 
			values (:project_id, :name, :address, :email, :phone, :site, :description, :logo) 
			returning id
		`)
		.pluck(true)
		.get(data)
}

function getCompany(id, project_id) {
	const row = db
		.prepare(`
			select id, name, address, email, phone, site, description, logo,
			(select json_group_array(user_id) from company_users where company_id = c.id) users
			from companies c 
			where c.id = :id and project_id = :project_id
			order by name
		`)
		.get({id, project_id})

	if (!row)
		throw Error('NOT_FOUND::404')

	row.users = JSON.parse(row.users || '[]')
	
	return row
}

app.get('/project/:pid(\\d+)/company', (req, res, next) => {
	const data = db
		.prepare(`
			select id, name, address, email, phone, site, description, logo,
			(select company_id = c.id from projects where id = :project_id) is_own,
			(select json_group_array(user_id) from company_users where company_id = c.id) users
			from companies c 
			where project_id = :project_id
			order by name
		`)
		.all(res.locals)

	data.forEach(row => {
		row.users = JSON.parse(row.users || '[]')
	})

	res.status(200).json({success: true, data})
})

app.get('/project/:pid(\\d+)/company/:cid(\\d+)', (req, res, next) => {
	const data = getCompany(req.params.cid, req.params.pid)
	res.status(200).json({success: true, data})
})

app.post('/project/:pid(\\d+)/company', (req, res, next) => {
	res.locals.name = req.body?.name
	res.locals.address = req.body?.address
	res.locals.email = req.body?.email
	res.locals.phone = req.body?.phone
	res.locals.site = req.body?.site
	res.locals.description = req.body?.description
	res.locals.logo = req.body?.logo

	const id = addCompany(res.locals)
	const data = getCompany(id, req.params.pid)
	res.status(200).json({success: true, data})
})

app.put('/project/:pid(\\d+)/company/:cid(\\d+)', (req, res, next) => {
	res.locals.id = parseInt(req.params.cid)
	res.locals.name = req.body?.name
	res.locals.address = req.body?.address
	res.locals.email = req.body?.email
	res.locals.phone = req.body?.phone
	res.locals.site = req.body?.site
	res.locals.description = req.body?.description
	res.locals.logo = req.body?.logo

	const info = db
		.prepareUpdate(
			'companies', 
			['name', 'address', 'email', 'phone', 'site', 'description', 'logo'], 
			res.locals, 
			['id', 'project_id'])
		.run(res.locals)
	
	if (info.changes == 0)
		throw Error('NOT_FOUND::404')

	const data = getCompany(req.params.cid, req.params.pid)
	res.status(200).json({success: true, data})
})

app.delete('/project/:pid(\\d+)/company/:cid(\\d+)', (req, res, next) => {
	res.locals.company_id = req.params.cid

	const info = db
		.prepare(`
			delete from companies 
			where id = :company_id and project_id = :project_id and 
				not exists(select company_id from projects where id = :project_id)`)
		.run(res.locals)	

	if (info.changes == 0)
		throw Error('NOT_FOUND::404')

	res.status(200).json({success: true, data: {id: req.params.cid}})
})

app.put('/project/:pid(\\d+)/company/:cid(\\d+)/user', (req, res, next) => {
	res.locals.company_id = parseInt(req.params.cid)

	// Проверка, что есть доступ к компании
	const row = db
		.prepare('select 1 from companies where id = :company_id and project_id = :project_id')
		.get(res.locals)

	if (!row)	
		throw Error('NOT_FOUND::404')

	const user_ids = req.body instanceof Array ? [...new Set(req.body.map(e => parseInt(e)))] : []

	// Проверка, что пользователи имеют доступ к проекту
	let rows = db
		.prepare(`
			select user_id 
			  from chat_users 
			 where chat_id in (select id from chats where project_id = :project_id)
		`)
		.pluck(true) // .raw?
		.get(res.locals)

	if (user_ids.some(user_id => !rows.contains(user_id)))
		throw Error('INACCESSABLE_MEMBER::400')

	// Проверка, что пользователи не участвуют в других компаниях на проекте
	rows = db
		.prepare(`
			select user_id 
			  from company_users 
			 where company_id in (select id from companies where id <> :company_id and project_id = :project_id)
		`)
		.pluck(true) // .raw?
		.get(res.locals)

	if (user_ids.some(user_id => !rows.contains(user_id)))
		throw Error('USED_MEMBER::400')

	db
		.prepare(`delete from company_users where company_id = :company_id`)
		.run(res.locals)

	db
		.prepare(`
			insert into company_users (company_id, user_id) 
			select :company_id, value from json_each(:json_ids)
		`)
		.run(res.locals, {json_ids: JSON.stringify(user_ids)})

	res.status(200).json({success: true})
})

app.get('/project/:pid(\\d+)/company/mapping', (req, res, next) => {
	const data = db
		.prepare(`
			select company_id, json_group_array(show_to_id) show_to_ids
			from company_mappings 
			where project_id = :project_id and company_id <> show_to_id
		`)
		.all(res.locals)	
	
	data.forEach(row => {
		row.show_to_ids = JSON.parse(row.show_to_ids || '[]')
	})	

	res.status(200).json({success: true, data})
})

app.put('/project/:pid(\\d+)/company/mapping', (req, res, next) => {
	if(!(req.body instanceof Array))
		throw Error('ARRAY_REQUIRED::500')

	db
		.prepare(`delete from company_mappings where project_id = :project_id`)
		.run(res.locals)

	req.body
		.filter(row => Number.isInteger(row.company_id) && row.show_to_ids instanceof Array && row.show_to_ids.every(id => Number.isInteger(id)))
		.forEach(row => {
			row.show_to_ids.push(row.company_id)

			const json_ids = row.show_to_ids.join(', ')
			const check = db
				.prepare(`select count(1) from companies where project_id = :project_id and id in (${json_ids}) `)
				.get(res.locals)
			
			if (check.count)	
				return console.error ('IGNORE: ', row)

			const locals = {
				project_ids: res.locals.project_id,
				company_id: row.company_id,
				json_ids
			}

			db
				.prepare(`
					insert into company_mappings (project_id, company_id, show_to_id) values 
					select :project_ids, :company_id, value from json_each(:json_ids)
				`)
				.run(locals)
		})

	res.status(200).json({success: true})
})

// CHATS
function getChat(id, project_id) {
	const row = db
		.prepare(`
			select  id, name, telegram_id, is_channel, invite_link, description, logo, user_count, bot_can_ban
			from chats c
			where c.id = :id and project_id = :project_id 
		`)
		.all({id, project_id})

	if (!row)
		throw Error('NOT_FOUND::404')

	row.is_channel = Boolean(row.is_channel)	
	row.bot_can_ban = Boolean(row.bot_can_ban)	

	return row
}

app.get('/project/:pid(\\d+)/chat', (req, res, next) => {
	const data = db
		.prepare(`
			select id, name, telegram_id, is_channel, invite_link, description, logo, user_count, bot_can_ban
			from chats 
			where project_id = :project_id
		`)
		.all(res.locals)

		data.forEach(row => {
			row.is_channel = Boolean(row.is_channel)
			row.bot_can_ban = Boolean(row.bot_can_ban)	
		})			

	res.status(200).json({success: true, data})
})

app.get('/project/:pid(\\d+)/chat/:gid(\\d+)', (req, res, next) => {
	const data = getChat(req.params.gid, req.params.pid)
	res.status(200).json({success: true, data})
})

app.delete('/project/:pid(\\d+)/chat/:gid(\\d+)', async (req, res, next) => {
	res.locals.chat_id = req.params.gid
	const info = db
		.prepare(`update chats set project_id = null where id = :chat_id and project_id = :project_id`)
		.run(res.locals)

	if (info.changes == 0)
		throw Error('NOT_FOUND::404')

	await bot.sendMessage(res.locals.chat_id, 'Чат удален из проекта')

	res.status(200).json({success: true, data: {id: req.params.gid}})
})

module.exports = app