import { BillingWebhookSecret, IsBillingEnabled } from "../EnvironmentConfig";
import UserMiddleware from "../Middleware/UserAuthorization";
import BillingService from "../Services/BillingService";
import ProjectService from "../Services/ProjectService";
import Express from "../Utils/Express";
import Response from "../Utils/Response";
import BadDataException from "../../Types/Exception/BadDataException";
import Permission from "../../Types/Permission";
import CommonAPI from "./CommonAPI";
import logger, { getLogAttributesFromRequest } from "../Utils/Logger";
export default class BillingAPI {
    constructor() {
        this.router = Express.getRouter();
        // Stripe webhook endpoint - uses raw body captured by JSON parser for signature verification
        this.router.post(`/billing/webhook`, async (req, res, next) => {
            try {
                logger.debug(`[Invoice Email] Webhook endpoint hit - /billing/webhook`, getLogAttributesFromRequest(req));
                if (!IsBillingEnabled) {
                    logger.debug(`[Invoice Email] Billing not enabled, returning early`, getLogAttributesFromRequest(req));
                    return Response.sendJsonObjectResponse(req, res, {
                        message: "Billing is not enabled",
                    });
                }
                if (!BillingWebhookSecret) {
                    logger.error(`[Invoice Email] Billing webhook secret is not configured`, getLogAttributesFromRequest(req));
                    throw new BadDataException("Billing webhook secret is not configured");
                }
                const signature = req.headers["stripe-signature"];
                logger.debug(`[Invoice Email] Stripe signature header present: ${Boolean(signature)}`, getLogAttributesFromRequest(req));
                if (!signature) {
                    logger.error(`[Invoice Email] Missing Stripe signature header`, getLogAttributesFromRequest(req));
                    throw new BadDataException("Missing Stripe signature header");
                }
                const rawBody = req.rawBody;
                logger.debug(`[Invoice Email] Raw body present: ${Boolean(rawBody)}, length: ${(rawBody === null || rawBody === void 0 ? void 0 : rawBody.length) || 0}`, getLogAttributesFromRequest(req));
                if (!rawBody) {
                    logger.error(`[Invoice Email] Missing raw body for webhook verification`, getLogAttributesFromRequest(req));
                    throw new BadDataException("Missing raw body for webhook verification");
                }
                logger.debug(`[Invoice Email] Verifying webhook signature...`, getLogAttributesFromRequest(req));
                const event = BillingService.verifyWebhookSignature(rawBody, signature);
                logger.debug(`[Invoice Email] Webhook signature verified successfully, event type: ${event.type}`, getLogAttributesFromRequest(req));
                // Handle the event asynchronously
                logger.debug(`[Invoice Email] Handling webhook event...`, getLogAttributesFromRequest(req));
                await BillingService.handleWebhookEvent(event);
                logger.debug(`[Invoice Email] Webhook event handled successfully`, getLogAttributesFromRequest(req));
                return Response.sendJsonObjectResponse(req, res, {
                    received: true,
                });
            }
            catch (err) {
                logger.error(`[Invoice Email] Stripe webhook error: ${err}`, getLogAttributesFromRequest(req));
                next(err);
            }
        });
        this.router.get(`/billing/customer-balance`, UserMiddleware.getUserMiddleware, async (req, res, next) => {
            var _a;
            try {
                if (!IsBillingEnabled) {
                    throw new BadDataException("Billing is not enabled for this server");
                }
                const userPermissions = (await this.getPermissionsForTenant(req)).filter((permission) => {
                    return (permission.permission.toString() ===
                        Permission.ProjectOwner.toString() ||
                        permission.permission.toString() ===
                            Permission.ManageProjectBilling.toString());
                });
                if (userPermissions.length === 0 &&
                    !((_a = req.userAuthorization) === null || _a === void 0 ? void 0 : _a.isMasterAdmin)) {
                    throw new BadDataException(`You need ${Permission.ProjectOwner} or ${Permission.ManageProjectBilling} permission to view billing balance.`);
                }
                const project = await ProjectService.findOneById({
                    id: this.getTenantId(req),
                    props: {
                        isRoot: true,
                    },
                    select: {
                        _id: true,
                        paymentProviderCustomerId: true,
                    },
                });
                if (!project) {
                    throw new BadDataException("Project not found");
                }
                if (!project.paymentProviderCustomerId) {
                    throw new BadDataException("Payment Provider customer not found");
                }
                const balance = await BillingService.getCustomerBalance(project.paymentProviderCustomerId);
                return Response.sendJsonObjectResponse(req, res, {
                    balance: balance,
                });
            }
            catch (err) {
                next(err);
            }
        });
    }
    async getPermissionsForTenant(req) {
        var _a, _b, _c;
        const permissions = [];
        const props = await CommonAPI.getDatabaseCommonInteractionProps(req);
        if (props &&
            props.userTenantAccessPermission &&
            props.userTenantAccessPermission[((_a = props.tenantId) === null || _a === void 0 ? void 0 : _a.toString()) || ""]) {
            return (((_c = props.userTenantAccessPermission[((_b = props.tenantId) === null || _b === void 0 ? void 0 : _b.toString()) || ""]) === null || _c === void 0 ? void 0 : _c.permissions) || []);
        }
        return permissions;
    }
    getTenantId(req) {
        if (req.tenantId) {
            return req.tenantId;
        }
        return null;
    }
    getRouter() {
        return this.router;
    }
}
//# sourceMappingURL=BillingAPI.js.map