import request from 'supertest';
import { createMockStripeEntitlementUpdatedData } from 'test/integration/billing/utils/create-mock-stripe-entitlement-updated-data.util';
import { createMockStripePriceCreatedData } from 'test/integration/billing/utils/create-mock-stripe-price-created-data.util';
import { createMockStripeProductUpdatedData } from 'test/integration/billing/utils/create-mock-stripe-product-updated-data.util';
import { createMockStripeSubscriptionCreatedData } from 'test/integration/billing/utils/create-mock-stripe-subscription-created-data.util';

const client = request(`http://localhost:${APP_PORT}`);

describe('BillingController (integration)', () => {
  it('should handle product.updated and price.created webhook events', async () => {
    const productUpdatedPayload = {
      type: 'product.updated',
      data: createMockStripeProductUpdatedData(),
    };
    const priceCreatedPayload = {
      type: 'price.created',
      data: createMockStripePriceCreatedData(),
    };

    await client
      .post('/billing/webhooks')
      .set('Authorization', `Bearer ${ADMIN_ACCESS_TOKEN}`)
      .set('stripe-signature', 'correct-signature')
      .set('Content-Type', 'application/json')
      .send(JSON.stringify(productUpdatedPayload))
      .expect(200)
      .then((res) => {
        expect(res.body.stripeProductId).toBeDefined();
      });

    await client
      .post('/billing/webhooks')
      .set('Authorization', `Bearer ${ADMIN_ACCESS_TOKEN}`)
      .set('stripe-signature', 'correct-signature')
      .set('Content-Type', 'application/json')
      .send(JSON.stringify(priceCreatedPayload))
      .expect(200)
      .then((res) => {
        expect(res.body.stripePriceId).toBeDefined();
        expect(res.body.stripeMeterId).toBeDefined();
      });
  });
  it('should handle subscription.created webhook event', async () => {
    const subscriptionCreatedPayload = {
      type: 'customer.subscription.created',
      data: createMockStripeSubscriptionCreatedData(),
    };
    const entitlementUpdatedPayload = {
      type: 'entitlements.active_entitlement_summary.updated',
      data: createMockStripeEntitlementUpdatedData(),
    };

    await client
      .post('/billing/webhooks')
      .set('Authorization', `Bearer ${ADMIN_ACCESS_TOKEN}`)
      .set('stripe-signature', 'correct-signature')
      .set('Content-Type', 'application/json')
      .send(JSON.stringify(subscriptionCreatedPayload))
      .expect(200)
      .then((res) => {
        expect(res.body.stripeSubscriptionId).toBeDefined();
        expect(res.body.stripeCustomerId).toBeDefined();
      });

    await client
      .post('/billing/webhooks')
      .set('Authorization', `Bearer ${ADMIN_ACCESS_TOKEN}`)
      .set('stripe-signature', 'correct-signature')
      .set('Content-Type', 'application/json')
      .send(JSON.stringify(entitlementUpdatedPayload))
      .expect(200)
      .then((res) => {
        expect(res.body.stripeEntitlementCustomerId).toBeDefined();
      });
  });

  it('should handle entitlements.active_entitlement_summary.updated when the subscription is not found', async () => {
    const entitlementUpdatedPayload = {
      type: 'entitlements.active_entitlement_summary.updated',
      data: createMockStripeEntitlementUpdatedData({
        customer: 'new_customer',
      }),
    };

    await client
      .post('/billing/webhooks')
      .set('Authorization', `Bearer ${ADMIN_ACCESS_TOKEN}`)
      .set('stripe-signature', 'correct-signature')
      .set('Content-Type', 'application/json')
      .send(JSON.stringify(entitlementUpdatedPayload))
      .expect(404);
  });

  it('should reject webhook with invalid signature', async () => {
    const entitlementUpdatedPayload = {
      type: 'customer.entitlement.created',
      data: {
        object: {
          id: 'ent_test123',
        },
      },
    };

    await client
      .post('/billing/webhooks')
      .set('Authorization', `Bearer ${ADMIN_ACCESS_TOKEN}`)
      .set('stripe-signature', 'invalid-signature')
      .set('Content-Type', 'application/json')
      .send(JSON.stringify(entitlementUpdatedPayload))
      .expect(500);
  });
});
