import {app} from "@/firebase";
import {CorporateUser, Group, MasterCorporateUser, StudentUser, TeacherUser} from "@/interfaces/user";
import {collection, doc, getDoc, getDocs, getFirestore, query, setDoc, where} from "firebase/firestore";
import moment from "moment";
import {getUser} from "./users.be";
import {getSpecificUsers} from "./users.be";
const db = getFirestore(app);

export const updateExpiryDateOnGroup = async (participantID: string, corporateID: string) => {
	const corporateRef = await getDoc(doc(db, "users", corporateID));
	const participantRef = await getDoc(doc(db, "users", participantID));

	if (!corporateRef.exists() || !participantRef.exists()) return;

	const corporate = {
		...corporateRef.data(),
		id: corporateRef.id,
	} as CorporateUser;
	const participant = {...participantRef.data(), id: participantRef.id} as StudentUser | TeacherUser;

	if (corporate.type !== "corporate" || (participant.type !== "student" && participant.type !== "teacher")) return;

	if (!corporate.subscriptionExpirationDate || !participant.subscriptionExpirationDate) {
		return await setDoc(doc(db, "users", participant.id), {subscriptionExpirationDate: null}, {merge: true});
	}

	const corporateDate = moment(corporate.subscriptionExpirationDate);
	const participantDate = moment(participant.subscriptionExpirationDate);

	if (corporateDate.isAfter(participantDate))
		return await setDoc(doc(db, "users", participant.id), {subscriptionExpirationDate: corporateDate.toISOString()}, {merge: true});

	return;
};

export const getUserCorporate = async (id: string) => {
	const user = await getUser(id);
	if (user.type === "mastercorporate") return user;

	const groups = await getParticipantGroups(id);
	const admins = await Promise.all(groups.map((x) => x.admin).map(getUser));
	const corporates = admins.filter((x) => x.type === "corporate" || x.type === "mastercorporate");

	if (corporates.length === 0) return undefined;
	return corporates.shift() as CorporateUser | MasterCorporateUser;
};

export const getGroups = async () => {
	const groupDocs = await getDocs(collection(db, "groups"));
	return groupDocs.docs.map((x) => ({...x.data(), id: x.id})) as Group[];
};

export const getParticipantGroups = async (id: string) => {
	const snapshot = await getDocs(query(collection(db, "groups"), where("participants", "array-contains", id)));

	const groups = snapshot.docs.map((doc) => ({
		id: doc.id,
		...doc.data(),
	})) as Group[];

	return groups;
};

export const getUserGroups = async (id: string): Promise<Group[]> => {
	const groupDocs = await getDocs(query(collection(db, "groups"), where("admin", "==", id)));
	return groupDocs.docs.map((x) => ({...x.data(), id})) as Group[];
};

export const getAllAssignersByCorporate = async (corporateID: string): Promise<string[]> => {
	const groups = await getUserGroups(corporateID);
	const groupUsers = (await Promise.all(groups.map(async (g) => await Promise.all(g.participants.map(getUser))))).flat();
	const teacherPromises = await Promise.all(
		groupUsers.map(async (u) =>
			u.type === "teacher" ? u.id : u.type === "corporate" ? [...(await getAllAssignersByCorporate(u.id)), u.id] : undefined,
		),
	);

	return teacherPromises.filter((x) => !!x).flat() as string[];
};

export const getGroupsForUser = async (admin: string, participant?: string) => {
	try {
		const queryConstraints = [
			...(admin ? [where("admin", "==", admin)] : []),
			...(participant ? [where("participants", "array-contains", participant)] : []),
		];
		const snapshot = await getDocs(queryConstraints.length > 0 ? query(collection(db, "groups"), ...queryConstraints) : collection(db, "groups"));
		const groups = snapshot.docs.map((doc) => ({
			id: doc.id,
			...doc.data(),
		})) as Group[];

		return groups;
	} catch (e) {
		console.error(e);
		return [];
	}
};

export const getStudentGroupsForUsersWithoutAdmin = async (admin: string, participants: string[]) => {
	try {
		const queryConstraints = [
			...(admin ? [where("admin", "!=", admin)] : []),
			...(participants ? [where("participants", "array-contains-any", participants)] : []),
			where("name", "==", "Students"),
		];
		const snapshot = await getDocs(queryConstraints.length > 0 ? query(collection(db, "groups"), ...queryConstraints) : collection(db, "groups"));
		const groups = snapshot.docs.map((doc) => ({
			id: doc.id,
			...doc.data(),
		})) as Group[];

		return groups;
	} catch (e) {
		console.error(e);
		return [];
	}
};

export const getCorporateNameForStudent = async (studentID: string) => {
	const groups = await getStudentGroupsForUsersWithoutAdmin("", [studentID]);
	if (groups.length === 0) return "";

	const adminUserIds = [...new Set(groups.map((g) => g.admin))];
	const adminUsersData = await getSpecificUsers(adminUserIds);

	if (adminUsersData.length === 0) return "";
	const admins = adminUsersData.filter((x) => x.type === "corporate");

	if (admins.length > 0) {
		return (admins[0] as CorporateUser).corporateInformation.companyInformation.name;
	}

	return "";
};
