let db = require('@config/database')

let Tag = module.exports = {}

Tag.userTags = (userId) => {
	return new Promise((resolve, reject) => {
		db.promise()
		.query(`
			SELECT tag.id, text, COUNT(note_tag.note_id) as usages FROM tag
			JOIN note_tag ON tag.id = note_tag.tag_id
			WHERE note_tag.user_id = ?
			GROUP BY tag.id
			ORDER BY id DESC
		`, [userId])
		.then( (rows, fields) => {
			resolve(rows[0])
		})
	})
}

Tag.removeTagFromNote = (userId, tagId) => {
	return new Promise((resolve, reject) => {
		db.promise()
		.query(`DELETE FROM note_tag WHERE id = ? AND user_id = ? LIMIT 1;`, [tagId, userId])
		.then((rows, fields) => {
			resolve(rows[0]) //Return new ID
		})
		.catch(console.log)
	})
}

Tag.addToNote = (userId, noteId, tagText) => {
	return new Promise((resolve, reject) => {

		//Lookup tag
		Tag.lookup(tagText)
		.then( lookup => {
			
			//Tag does not exist, insert new tag, then associate it with a note
			if(lookup.length == 0){
				//Insert new tag
				Tag.add(tagText)
				.then( newTagId => {
					Tag.associateWithNote(userId, noteId, newTagId)
					.then( result => {
						resolve(result)
					})
				})
			}

			//Tag already exists, associate it with a note
			if(lookup.length > 0){
				Tag.associateWithNote(userId, noteId, lookup[0].id)
				.then( result => {
					resolve(result)
				})
			}

		})
	})
}

Tag.associateWithNote = (userId, noteId, tagId) => {
	return new Promise((resolve, reject) => {

		//Check if tag already exists on note before adding note
		db.promise()
		.query(`SELECT * FROM note_tag WHERE note_id = ? AND tag_id = ? AND user_id = ?;`, [noteId, tagId, userId])
		.then((rows, fields) => {

			//If matching tag does not exist on note
			if(rows[0].length == 0){

				//Add tag to note
				db.promise()
				.query(`INSERT INTO note_tag (note_id, tag_id, user_id) VALUES (?,?,?);`, [noteId, tagId, userId])
				.then((rows, fields) => {
					resolve(rows[0]) 
				})
				.catch(console.log)
			} else {

				reject('Error: Tag already exists on note.')
			}
		})
		.catch(console.log)
	})
}

Tag.add = (tagText) => {
	return new Promise((resolve, reject) => {
		db.promise()
		.query(`INSERT INTO tag (text, hash) VALUES (?,?);`, [tagText,0])
		.then((rows, fields) => {
			resolve(rows[0].insertId) //Return new ID
		})
		.catch(console.log)
	})
}

//
// Get all tags AND tags associated to note
//
Tag.get = (userId, noteId) => {
	return new Promise((resolve, reject) => {

		Tag.userTags(userId).then(userTags => {
			db.promise()
			.query(`SELECT tag_id as tagId, id as entryId
					FROM note_tag
					WHERE user_id = ? AND note_id = ?;`, [userId, noteId])
			.then((rows, fields) => {

				//pull IDs out of returned results
				// let ids = rows[0].map( item => {})

				resolve({'noteTagIds':rows[0], 'allTags':userTags }) //Return all tags found by query
			})
			.catch(console.log)
		})
		
	})
}

//
// Get all tags for a note and concatinate into a string 'all, tags, like, this'
//
Tag.string = (userId, noteId) => {
	return new Promise((resolve, reject) => {
		db.promise()
		.query(`SELECT GROUP_CONCAT(DISTINCT tag.text SEPARATOR ', ') as text
				FROM note_tag
				JOIN tag ON note_tag.tag_id = tag.id
				WHERE user_id = ? AND note_id = ?;`, [userId, noteId])
		.then((rows, fields) => {

			let finalText = rows[0][0]['text']
			if(finalText == null){
				finalText = ''
			}

			return resolve(finalText) //Return all tags found by query
		})
		.catch(console.log)
	})
}

Tag.lookup = (tagText) => {
	return new Promise((resolve, reject) => {
		db.promise()
		.query(`SELECT * FROM tag WHERE text = ?;`, [tagText])
		.then((rows, fields) => {
			resolve(rows[0]) //Return all tags found by query
		})
		.catch(console.log)
	})
}

//Suggest note tags - don't suggest tags already on note
Tag.suggest = (userId, noteId, tagText) => {

	tagText += '%'

	return new Promise((resolve, reject) => {
		db.promise()
		.query(`SELECT text FROM note_tag 
				JOIN tag ON note_tag.tag_id = tag.id
				WHERE note_tag.user_id = ?
				AND tag.text LIKE ?
				AND note_tag.tag_id NOT IN (
					SELECT note_tag.tag_id FROM note_tag WHERE note_tag.note_id = ?
				)
				GROUP BY text
				LIMIT 6`, [userId, tagText, noteId])
		.then((rows, fields) => {
			resolve(rows[0]) //Return new ID
		})
		.catch(console.log)
	})
}

//Latest Tags - don't suggest tags already on note
Tag.latest = (userId, noteId) => {

	return new Promise((resolve, reject) => {
		db.promise()
		.query(`SELECT tag.text FROM note_tag 
				JOIN tag ON note_tag.tag_id = tag.id
				JOIN note ON note_tag.note_id = note.id
				WHERE note_tag.user_id = ?
				AND note_tag.tag_id NOT IN (
					SELECT note_tag.tag_id FROM note_tag WHERE note_tag.note_id = ?
				)
				GROUP BY tag.text, note.updated
				ORDER BY note.updated DESC
				LIMIT 8;`, [userId, noteId])
		.then((rows, fields) => {
			resolve(rows[0]) //Return found tags
		})
		.catch(console.log)
	})
}