const passport = require('passport');
const { Members } = require('../../../models');
const { formatCase } = require('../../formatter');
const { Op } = require('sequelize');
const CustomStrategy = require('passport-custom').Strategy;
const LocalStrategy = require('passport-local').Strategy;

passport.use(
	'signup-member',
	new CustomStrategy(async (req, done) => {
		try {
			const {
				organization_name,
				is_jci_senator,
				local_org_name,
				first_name,
				last_name,
				email_address,
				password,
				is_tnc_agreed,
			} = formatCase(req.body, 'snake');

			const existingUser = await Members.findOne({
				where: {
					email_address: email_address,
				},
			});

			if (existingUser) {
				return done(null, false, { message: 'Email address is already in use.' });
			}

			async function generateAccountId() {
				const maxAccount = await Members.findOne({
					attributes: [[Members.sequelize.fn('MAX', Members.sequelize.col('account_id')), 'maxAccountId']],
				});
				let nextAccountId = (parseInt(maxAccount.get('maxAccountId'), 10) || 0) + 1;

				let exists = await Members.findOne({ where: { account_id: nextAccountId } });
				while (exists) {
					nextAccountId++;
					exists = await Members.findOne({ where: { account_id: nextAccountId } });
				}
				return nextAccountId;
			}

			const account_id = await generateAccountId();

			const member = await Members.create({
				organization_name,
				account_id,
				is_jci_senator,
				local_org_name,
				first_name,
				last_name,
				email_address,
				password,
				is_tnc_agreed,
			});

			return done(null, member);
		} catch (error) {
			done(error);
		}
	}),
);

passport.use(
	'login-member',
	new LocalStrategy(
		{ usernameField: 'emailAddress', passReqToCallback: true },
		async (req, emailAddress, password, done) => {
			try {
				const member = await Members.findOne({
					where: {
						email_address: emailAddress,
					},
				});

				if (!member || !(await member.validatePassword(password))) {
					return done(null, false, { message: 'Invalid email/phone or password' });
				}

				return done(null, member);
			} catch (error) {
				return done(error);
			}
		},
	),
);

passport.serializeUser((member, done) => {
	done(null, member.id);
});

passport.deserializeUser(async (id, done) => {
	try {
		const member = await Members.findByPk(id);
		done(null, member);
	} catch (error) {
		done(error);
	}
});

module.exports = passport;
