import type { BlitzApiHandler } from "blitz";
import { NotFoundError } from "blitz";
import { z } from "zod";

import type { ApiError } from "../../core/types";
import db, { MembershipRole } from "db";
import appLogger from "../../../integrations/logger";
import { sendEmail } from "../../../integrations/ses";

const logger = appLogger.child({ module: "subscription-updated" });

export const subscriptionUpdated: BlitzApiHandler = async (req, res) => {
	const validationResult = bodySchema.safeParse(req.body);
	if (!validationResult.success) {
		const statusCode = 400;
		const apiError: ApiError = {
			statusCode,
			errorMessage: "Body is malformed",
		};
		logger.error(validationResult.error, "/api/subscription/webhook");

		res.status(statusCode).send(apiError);
		return;
	}

	const body = validationResult.data;
	const paddleSubscriptionId = body.subscription_id;
	const subscription = await db.subscription.findFirst({
		where: { paddleSubscriptionId },
		include: {
			organization: {
				include: {
					memberships: {
						include: { user: true },
					},
				},
			},
		},
	});
	if (!subscription) {
		throw new NotFoundError();
	}

	const lastEventTime = new Date(body.event_time);
	const isEventOlderThanLastUpdate = subscription.lastEventTime > lastEventTime;
	if (isEventOlderThanLastUpdate) {
		res.status(200).end();
		return;
	}

	const orgOwner = subscription.organization!.memberships.find(
		(membership) => membership.role === MembershipRole.OWNER,
	);
	const email = orgOwner!.user!.email;
	const paddleCheckoutId = body.checkout_id;
	const planId = body.subscription_plan_id;
	const nextBillDate = new Date(body.next_bill_date);
	const status = body.status;
	const updateUrl = body.update_url;
	const cancelUrl = body.cancel_url;
	const currency = body.currency;
	const unitPrice = body.new_unit_price;

	await db.subscription.update({
		where: { paddleSubscriptionId },
		data: {
			paddleSubscriptionId,
			paddlePlanId: planId,
			paddleCheckoutId,
			nextBillDate,
			status,
			lastEventTime,
			updateUrl,
			cancelUrl,
			currency,
			unitPrice,
		},
	});

	sendEmail({
		subject: "Thanks for your purchase",
		body: "Thanks for your purchase",
		recipients: [email],
	}).catch((error) => {
		logger.error(error, "/api/subscription/webhook");
	});

	return res.status(200).end();
};

const bodySchema = z.object({
	alert_id: z.string(),
	alert_name: z.string(),
	cancel_url: z.string(),
	checkout_id: z.string(),
	currency: z.string(),
	email: z.string(),
	event_time: z.string(),
	linked_subscriptions: z.string(),
	marketing_consent: z.string(),
	new_price: z.string(),
	new_quantity: z.string(),
	new_unit_price: z.string(),
	next_bill_date: z.string(),
	old_next_bill_date: z.string(),
	old_price: z.string(),
	old_quantity: z.string(),
	old_status: z.string(),
	old_subscription_plan_id: z.string(),
	old_unit_price: z.string(),
	passthrough: z.string(),
	status: z.enum(["active", "trialing", "past_due", "paused", "deleted"]),
	subscription_id: z.string(),
	subscription_plan_id: z.string(),
	update_url: z.string(),
	user_id: z.string(),
	p_signature: z.string(),
});