{"size": 2269, "ext": "js", "max_stars_repo_path": "packages/payments/lib/payments.js", "max_stars_repo_name": "allouis/Members", "max_stars_repo_stars_event_min_datetime": "2019-06-01T23:57:41.000Z", "max_stars_repo_stars_event_max_datetime": "2021-11-25T18:42:34.000Z", "max_issues_repo_path": "packages/payments/lib/payments.js", "max_issues_repo_name": "allouis/Members", "max_issues_repo_issues_event_min_datetime": "2019-03-19T14:33:18.000Z", "max_issues_repo_issues_event_max_datetime": "2022-03-22T12:07:13.000Z", "max_forks_repo_path": "packages/payments/lib/payments.js", "max_forks_repo_name": "allouis/Members", "max_forks_repo_forks_event_min_datetime": "2019-04-05T08:06:02.000Z", "max_forks_repo_forks_event_max_datetime": "2022-03-09T00:03:16.000Z"}
{"max_stars_count": 25, "max_issues_count": 70, "max_forks_count": 34, "avg_line_length": 29.8552631579, "max_line_length": 106, "alphanum_fraction": 0.5817540767}
const DomainEvents = require('@tryghost/domain-events');
const OfferCreatedEvent = require('@tryghost/members-offers').events.OfferCreatedEvent;

class PaymentsService {
    /**
     * @param {object} deps
     * @param {any} deps.Offer
     * @param {import('@tryghost/members-offers/lib/application/OffersAPI')} deps.offersAPI
     * @param {any} deps.stripeAPIService
     */
    constructor(deps) {
        /** @private */
        this.OfferModel = deps.Offer;
        /** @private */
        this.offersAPI = deps.offersAPI;
        /** @private */
        this.stripeAPIService = deps.stripeAPIService;

        DomainEvents.subscribe(OfferCreatedEvent, async (event) => {
            await this.getCouponForOffer(event.data.offer.id);
        });
    }

    /**
     * @param {string} offerId
     *
     * @returns {Promise<{id: string}>}
     */
    async getCouponForOffer(offerId) {
        const row = await this.OfferModel.where({id: offerId}).query().select('stripe_coupon_id').first();
        if (!row) {
            return null;
        }
        if (!row.stripe_coupon_id) {
            const offer = await this.offersAPI.getOffer({id: offerId});
            await this.createCouponForOffer(offer);
            return this.getCouponForOffer(offerId);
        }
        return {
            id: row.stripe_coupon_id
        };
    }

    /**
     * @param {import('@tryghost/members-offers/lib/application/OfferMapper').OfferDTO} offer
     */
    async createCouponForOffer(offer) {
        /** @type {import('stripe').Stripe.CouponCreateParams} */
        const couponData = {
            name: offer.name,
            duration: offer.duration
        };

        if (offer.duration === 'repeating') {
            couponData.duration_in_months = offer.duration_in_months;
        }

        if (offer.type === 'percent') {
            couponData.percent_off = offer.amount;
        } else {
            couponData.amount_off = offer.amount;
            couponData.currency = offer.currency;
        }

        const coupon = await this.stripeAPIService.createCoupon(couponData);

        await this.OfferModel.edit({
            stripe_coupon_id: coupon.id
        }, {
            id: offer.id
        });
    }
}

module.exports = PaymentsService;
