// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import type {NextApiRequest, NextApiResponse} from "next";
import {app} from "@/firebase";
import {getFirestore, collection, getDocs, setDoc, doc, getDoc, query, where} from "firebase/firestore";
import {withIronSessionApiRoute} from "iron-session/next";
import {sessionOptions} from "@/lib/session";
import {Group, User} from "@/interfaces/user";
import {DurationUnit, Package, Payment} from "@/interfaces/paypal";
import {v4} from "uuid";
import ShortUniqueId from "short-unique-id";
import axios from "axios";
import {IntentionResult, PaymentIntention, TransactionResult} from "@/interfaces/paymob";
import moment from "moment";

const db = getFirestore(app);

export default async function handler(req: NextApiRequest, res: NextApiResponse) {
	if (req.method === "POST") await post(req, res);
}

async function post(req: NextApiRequest, res: NextApiResponse) {
	const transactionResult = req.body as TransactionResult;
	const authToken = await authenticatePaymob();

	console.log("WEBHOOK: ", transactionResult);
	if (!checkTransaction(authToken, transactionResult.transaction.order.id)) return res.status(404).json({ok: false});
	if (!transactionResult.transaction.success) return res.status(400).json({ok: false});

	const {userID, duration, duration_unit} = transactionResult.intention.extras.creation_extras as {
		userID: string;
		duration: number;
		duration_unit: DurationUnit;
	};

	const userSnapshot = await getDoc(doc(db, "users", userID as string));

	if (!userSnapshot.exists() || !duration || !duration_unit) return res.status(404).json({ok: false});

	const user = {...userSnapshot.data(), id: userSnapshot.id} as User;

	const subscriptionExpirationDate = user.subscriptionExpirationDate;
	if (!subscriptionExpirationDate) return res.status(200).json({ok: false});

	const initialDate = moment(subscriptionExpirationDate).isAfter(moment()) ? moment(subscriptionExpirationDate) : moment();

	const updatedSubscriptionExpirationDate = moment(initialDate).add(duration, duration_unit).endOf("day").subtract(2, "hours").toISOString();

	await setDoc(userSnapshot.ref, {subscriptionExpirationDate: updatedSubscriptionExpirationDate, status: "active"}, {merge: true});
	await setDoc(doc(db, "paypalpayments", v4()), {
		createdAt: new Date().toISOString(),
		currency: transactionResult.transaction.currency,
		orderId: transactionResult.transaction.id,
		status: "COMPLETED",
		subscriptionDuration: duration,
		subscriptionDurationUnit: duration_unit,
		subscriptionExpirationDate: updatedSubscriptionExpirationDate,
		userId: userID,
		value: transactionResult.transaction.amount_cents / 1000,
	});

	if (user.type === "corporate") {
		const groupsSnapshot = await getDocs(query(collection(db, "groups"), where("admin", "==", user.id)));
		const groups = groupsSnapshot.docs.map((g) => ({...g.data(), id: g.id})) as Group[];

		const participants = (await Promise.all(
			groups.flatMap((x) => x.participants).map(async (x) => ({...(await getDoc(doc(db, "users", x))).data(), id: x})),
		)) as User[];
		const sameExpiryDateParticipants = participants.filter(
			(x) => x.subscriptionExpirationDate === subscriptionExpirationDate && x.status !== "disabled",
		);

		for (const participant of sameExpiryDateParticipants) {
			await setDoc(
				doc(db, "users", participant.id),
				{subscriptionExpirationDate: updatedSubscriptionExpirationDate, status: "active"},
				{merge: true},
			);
		}
	}

	res.status(200).json({
		ok: true,
	});
}

const authenticatePaymob = async () => {
	const response = await axios.post<{token: string}>(
		"https://oman.paymob.com/api/auth/tokens",
		{
			api_key: process.env.PAYMOB_API_KEY,
		},
		{headers: {Authorization: `Bearer ${process.env.PAYMOB_SECRET_KEY}`}},
	);

	return response.data.token;
};

const checkTransaction = async (token: string, orderID: number) => {
	const response = await axios.post("https://oman.paymob.com/api/ecommerce/orders/transaction_inquiry", {auth_token: token, order_id: orderID});

	return response.status === 200;
};
