const UserModel = require('../model/user');
const fs = require('fs').promises;
const path = require('path');
const Jimp = require('jimp');
const jwt = require('jsonwebtoken');
const createFolderIsExist = require('../helpers/create-directory');
require('dotenv').config();
const client = require('../helpers/twilio');
const phoneToken = require('generate-sms-verification-code');
const SECRET_KEY = process.env.JWT_SECRET;

const createNewUser = async (req, res, next) => {
	try {
		const code = phoneToken(4, { type: 'number' });
		const color = `#${Math.floor(Math.random() * 16777215).toString(16)}`;
		const { number, country } = req.body;
		const isExist = await UserModel.findByNumber(number);
		if (isExist) {
			await UserModel.updateCode(isExist._id, code);
		} else {
			await UserModel.createUser({ number, country, color, code });
		}
		client.messages.create({
			body: `${code}`,
			to: `${number}`,
			from: '+18305875860',
		});
		return res.status(201).json({
			status: 'success',
			code: 201,
			data: String(code),
		});
	} catch (e) {
		next(e);
	}
};

const logIn = async (req, res, next) => {
	try {
		const { number, code } = req.body;
		const user = await UserModel.findByNumber(number);
		if (!user || user.code !== code)
			return res.status(401).json({
				status: 'error',
				code: 401,
				data: 'UNAUTHORIZED',
				message: 'Invalid credentials',
			});
		const id = user._id;
		const payload = { id };
		const token = jwt.sign(payload, SECRET_KEY, { expiresIn: '24h' });
		let registered = true;
		if (!user.name || !user.lastName || !user.avatarUrl) registered = false;
		await UserModel.updateUser(id, { token, code: '', online: true });
		return res.status(200).json({
			status: 'success',
			code: 200,
			data: {
				token,
				registered,
			},
		});
	} catch (e) {
		next(e);
	}
};

const logOut = async (req, res, next) => {
	try {
		const id = req.user.id;
		const user = await UserModel.findById(id);
		if (!user)
			return res.status(401).json({
				status: 'error',
				code: 401,
				data: 'UNAUTHORIZED',
				message: 'Invalid credentials',
			});
		await UserModel.updateUser(id, { token: null, online: new Date() });
		return res.status(204).json({});
	} catch (e) {
		next(e);
	}
};

const online = async (req, res, next) => {
	try {
		const id = req.user.id;
		const user = await UserModel.findById(id);
		if (!user)
			return res.status(401).json({
				status: 'error',
				code: 401,
				data: 'UNAUTHORIZED',
				message: 'Invalid credentials',
			});
		await UserModel.updateUser(id, { online: new Date() });
		return res.status(204).json({});
	} catch (e) {
		next(e);
	}
};

const getCurrent = async (req, res, next) => {
	try {
		const user = req.user;
		if (!user)
			return res.status(401).json({
				status: 'error',
				code: 401,
				data: 'UNAUTHORIZED',
				message: 'Invalid credentials',
			});
		const id = req.user.id;
		await UserModel.updateUser(id, { online: true });
		const updatedUser = await UserModel.findById(id);
		return res.status(200).json({
			status: 'success',
			code: 200,
			data: updatedUser,
		});
	} catch (e) {
		next(e);
	}
};

const updateCredentials = async (req, res, next) => {
	try {
		const { id, token } = req.user;
		await UserModel.updateCredentials(id, req.body);
		return res.status(200).json({
			data: {
				token,
			},
		});
	} catch (e) {
		next(e);
	}
};

const updateAvatar = async (req, res, next) => {
	try {
		const userId = req.user.id;
		const token = req.user.token;
		const DIR_IMAGES = process.env.DIR_IMAGES;
		const pathToFile = req.file.path;
		const newNameAvatar = req.file.originalname;
		const img = await Jimp.read(pathToFile);
		await img
			.autocrop()
			.cover(
				250,
				250,
				Jimp.HORIZONTAL_ALIGN_CENTER | Jimp.VERTICAL_ALIGN_MIDDLE
			)
			.writeAsync(pathToFile);
		await createFolderIsExist(path.join(DIR_IMAGES, userId));
		await fs.rename(pathToFile, path.join(DIR_IMAGES, userId, newNameAvatar));
		const avatarUrl = path.normalize(path.join(userId, newNameAvatar));
		await UserModel.updateAvatar(userId, avatarUrl);
		return res.status(200).json({
			status: 'success',
			code: 200,
			data: {
				token,
			},
		});
	} catch (e) {
		next(e);
	}
};

module.exports = {
	createNewUser,
	logIn,
	logOut,
	online,
	getCurrent,
	updateCredentials,
	updateAvatar,
};
