const require_rolldown_runtime = require('../_virtual/rolldown_runtime.cjs');
const require_logger_index = require('../logger/index.cjs');
const require_utils_errors_ErrorsClass = require('../utils/errors/ErrorsClass.cjs');
const require_services_organization_service = require('./organization.service.cjs');
const require_services_user_service = require('./user.service.cjs');
const require_services_email_service = require('./email.service.cjs');
const require_utils_plan = require('../utils/plan.cjs');
let stripe = require("stripe");
stripe = require_rolldown_runtime.__toESM(stripe);

//#region src/services/subscription.service.ts
const addOrUpdateSubscription = async (subscriptionId, priceId, customerId, userId, organization, status) => {
	const stripe$1 = new stripe.default(process.env.STRIPE_SECRET_KEY);
	const user = await require_services_user_service.getUserById(userId);
	if (!user) throw new require_utils_errors_ErrorsClass.GenericError("USER_NOT_FOUND", { userId });
	if (String(user.customerId) !== customerId) {
		user.customerId = customerId;
		await user.save();
	}
	const planInfo = require_utils_plan.retrievePlanInformation(priceId);
	const subscriptions = await stripe$1.subscriptions.list({
		customer: customerId,
		status: "active",
		limit: 1
	});
	if (subscriptions.data.length >= 1) {
		const otherSubscriptionArray = subscriptions.data.filter((subscription) => subscription.id !== subscriptionId);
		for (const subscription of otherSubscriptionArray) await stripe$1.subscriptions.cancel(subscription.id);
	}
	const updatedOrganization = await require_services_organization_service.updatePlan(organization, {
		creatorId: user.id,
		priceId,
		customerId,
		subscriptionId,
		type: planInfo.type,
		period: planInfo.period,
		status
	});
	if (!updatedOrganization) throw new require_utils_errors_ErrorsClass.GenericError("ORGANIZATION_UPDATE_FAILED", { organizationId: organization.id });
	require_logger_index.logger.info(`Plan updated for organization ${organization.id} - ${planInfo.type} - ${planInfo.period}`);
	return updatedOrganization.plan ?? null;
};
const cancelSubscription = async (subscriptionId, organizationId) => {
	const organization = await require_services_organization_service.getOrganizationById(organizationId);
	if (!organization) throw new require_utils_errors_ErrorsClass.GenericError("ORGANIZATION_NOT_FOUND", { subscriptionId });
	if (!subscriptionId) throw new require_utils_errors_ErrorsClass.GenericError("NO_SUBSCRIPTION_ID_PROVIDED");
	if (!organization.plan) throw new require_utils_errors_ErrorsClass.GenericError("ORGANIZATION_PLAN_NOT_FOUND", {
		subscriptionId,
		organizationId: organization.id
	});
	const updatedOrganization = await require_services_organization_service.updatePlan(organization, { status: "canceled" });
	if (!updatedOrganization) throw new require_utils_errors_ErrorsClass.GenericError("ORGANIZATION_UPDATE_FAILED", { organizationId: organization.id });
	require_logger_index.logger.info(`Cancelled plan for organization ${updatedOrganization.id} - ${updatedOrganization.plan?.type} - ${updatedOrganization.plan?.period}`);
	return updatedOrganization.plan ?? null;
};
const changeSubscriptionStatus = async (subscriptionId, status, userId, organizationId) => {
	const organization = await require_services_organization_service.getOrganizationById(organizationId);
	if (!organization) throw new require_utils_errors_ErrorsClass.GenericError("ORGANIZATION_NOT_FOUND", {
		userId,
		subscriptionId
	});
	if (!organization.plan) throw new require_utils_errors_ErrorsClass.GenericError("ORGANIZATION_PLAN_NOT_FOUND", {
		userId,
		subscriptionId,
		organizationId: organization.id
	});
	const updatedOrganization = await require_services_organization_service.updatePlan(organization, {
		status,
		subscriptionId
	});
	if (!updatedOrganization) throw new require_utils_errors_ErrorsClass.GenericError("ORGANIZATION_UPDATE_FAILED", { organizationId: organization.id });
	const user = await require_services_user_service.getUserById(userId);
	if (!user) throw new require_utils_errors_ErrorsClass.GenericError("USER_NOT_FOUND", {
		userId,
		subscriptionId
	});
	require_logger_index.logger.info(`Updated plan status for organization ${organization.id} - Status: ${status}`);
	const emailData = {
		to: user.email,
		username: user.name,
		email: user.email,
		planName: organization.plan.type,
		date: (/* @__PURE__ */ new Date()).toLocaleDateString(),
		link: `${process.env.CLIENT_URL}/dashboard`
	};
	switch (status) {
		case "active":
			await require_services_email_service.sendEmail({
				...emailData,
				type: "subscriptionPaymentSuccess",
				organizationName: organization.name,
				subscriptionStartDate: emailData.date,
				manageSubscriptionLink: emailData.link
			});
			break;
		case "canceled":
			await require_services_email_service.sendEmail({
				...emailData,
				type: "subscriptionPaymentCancellation",
				organizationName: organization.name,
				cancellationDate: emailData.date,
				reactivateLink: emailData.link
			});
			break;
		case "incomplete":
			await require_services_email_service.sendEmail({
				...emailData,
				type: "subscriptionPaymentError",
				organizationName: organization.name,
				errorDate: emailData.date,
				retryPaymentLink: emailData.link
			});
			break;
		default: require_logger_index.logger.warn(`Unhandled subscription status: ${status}`);
	}
	return updatedOrganization.plan ?? null;
};
const getCouponId = async (promoCode) => {
	const stripe$1 = new stripe.default(process.env.STRIPE_SECRET_KEY);
	try {
		const matchingCoupon = (await stripe$1.coupons.list()).data.find((coupon) => coupon.name === promoCode);
		return matchingCoupon ? matchingCoupon.id : null;
	} catch (error) {
		console.error("Error retrieving coupon:", error);
		return null;
	}
};
const getPricing = async (priceIds, promoCode) => {
	const stripe$1 = new stripe.default(process.env.STRIPE_SECRET_KEY);
	try {
		const pricePromises = priceIds.map((priceId) => stripe$1.prices.retrieve(priceId));
		const prices = await Promise.all(pricePromises);
		const totalAmount = prices.reduce((sum, price) => sum + (price.unit_amount ?? 0), 0);
		let discountAmount = 0;
		let discountType = null;
		if (promoCode) {
			const matchingCoupons = (await stripe$1.coupons.list()).data.find((coupon) => coupon.name === promoCode);
			if (matchingCoupons) {
				if (matchingCoupons.amount_off) {
					discountAmount = matchingCoupons.amount_off;
					discountType = "amount";
				} else if (matchingCoupons.percent_off) {
					discountAmount = matchingCoupons.percent_off;
					discountType = "percentage";
				}
			}
		}
		const results = {};
		for (const price of prices) {
			if (!price.id || !price.unit_amount) continue;
			const originalTotal = price.unit_amount;
			let appliedDiscount = 0;
			let finalTotal = originalTotal;
			if (discountType === "percentage" && discountAmount > 0) {
				appliedDiscount = originalTotal * discountAmount / 100;
				finalTotal = originalTotal - appliedDiscount;
			} else if (discountType === "amount" && totalAmount > 0 && discountAmount > 0) {
				const proportion = originalTotal / totalAmount;
				appliedDiscount = discountAmount * proportion;
				finalTotal = originalTotal - appliedDiscount;
			}
			finalTotal = Math.max(finalTotal, 0);
			results[price.id] = {
				originalTotal,
				discountApplied: appliedDiscount,
				discountType,
				finalTotal,
				currency: price.currency
			};
		}
		return results;
	} catch (error) {
		console.error("Error calculating pricing per priceId:", error);
		throw new Error("Failed to calculate pricing breakdown.");
	}
};

//#endregion
exports.addOrUpdateSubscription = addOrUpdateSubscription;
exports.cancelSubscription = cancelSubscription;
exports.changeSubscriptionStatus = changeSubscriptionStatus;
exports.getCouponId = getCouponId;
exports.getPricing = getPricing;
//# sourceMappingURL=subscription.service.cjs.map