import { test, expect, registerUser } from '../fixtures';

test.describe('Subscriptions API', () => {
  let accessToken: string;

  test.beforeAll(async ({ request }) => {
    const { accessToken: token } = await registerUser(request);
    accessToken = token;
  });

  test.describe('GET /subscriptions/plans — List plans', () => {
    test('returns all available subscription plans', async ({ request }) => {
      const res = await request.get('subscriptions/plans');

      expect(res.status()).toBe(200);
      const body = await res.json();
      expect(Array.isArray(body)).toBeTruthy();
      expect(body.length).toBeGreaterThan(0);

      // Verify plan structure
      const plan = body[0];
      expect(plan).toHaveProperty('tier');
      expect(plan).toHaveProperty('name');
      expect(plan).toHaveProperty('priceMonthlyVND');
    });

    test('includes FREE tier in plans', async ({ request }) => {
      const res = await request.get('subscriptions/plans');
      const body = await res.json();

      const freePlan = body.find((p: { tier: string }) => p.tier === 'FREE');
      expect(freePlan).toBeDefined();
    });
  });

  test.describe('GET /subscriptions/plans/:tier — Get specific plan', () => {
    test('returns plan details for FREE tier', async ({ request }) => {
      const res = await request.get('subscriptions/plans/FREE');

      expect(res.status()).toBe(200);
      const body = await res.json();
      expect(body.tier).toBe('FREE');
      expect(body).toHaveProperty('name');
      expect(body).toHaveProperty('maxListings');
    });

    test('returns plan details for AGENT_PRO tier', async ({ request }) => {
      const res = await request.get('subscriptions/plans/AGENT_PRO');

      expect(res.status()).toBe(200);
      const body = await res.json();
      expect(body.tier).toBe('AGENT_PRO');
    });

    test('returns 404 for non-existent tier', async ({ request }) => {
      const res = await request.get('subscriptions/plans/NONEXISTENT');

      expect(res.ok()).toBeFalsy();
      expect([404, 400]).toContain(res.status());
    });
  });

  test.describe('POST /subscriptions — Create subscription', () => {
    test('creates a FREE subscription', async ({ request }) => {
      const res = await request.post('subscriptions', {
        data: { planTier: 'FREE', billingCycle: 'monthly' },
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      // May succeed or conflict if user already has subscription
      expect([201, 409]).toContain(res.status());
      if (res.status() === 201) {
        const body = await res.json();
        expect(body).toHaveProperty('subscriptionId');
        expect(body).toHaveProperty('planTier');
      }
    });

    test('rejects subscription with invalid plan tier', async ({ request }) => {
      const res = await request.post('subscriptions', {
        data: { planTier: 'INVALID_TIER', billingCycle: 'monthly' },
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      expect(res.ok()).toBeFalsy();
      expect(res.status()).toBe(400);
    });

    test('rejects subscription with invalid billing cycle', async ({ request }) => {
      const res = await request.post('subscriptions', {
        data: { planTier: 'FREE', billingCycle: 'weekly' },
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      expect(res.ok()).toBeFalsy();
      expect(res.status()).toBe(400);
    });

    test('rejects unauthenticated subscription creation', async ({ request }) => {
      const res = await request.post('subscriptions', {
        data: { planTier: 'FREE', billingCycle: 'monthly' },
      });

      expect(res.status()).toBe(401);
    });
  });

  test.describe('GET /subscriptions/quota/:metric — Check quota', () => {
    test('returns quota for listings metric', async ({ request }) => {
      // Ensure user has a subscription first
      await request.post('subscriptions', {
        data: { planTier: 'FREE', billingCycle: 'monthly' },
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      const res = await request.get('subscriptions/quota/listings', {
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      // 200 if subscription exists, 404 if no subscription
      if (res.status() === 200) {
        const body = await res.json();
        expect(body).toHaveProperty('limit');
        expect(body).toHaveProperty('used');
        expect(body).toHaveProperty('remaining');
      }
    });

    test('rejects unauthenticated quota check', async ({ request }) => {
      const res = await request.get('subscriptions/quota/listings');

      expect(res.status()).toBe(401);
    });
  });

  test.describe('POST /subscriptions/usage — Meter usage', () => {
    test('meters usage for authenticated user', async ({ request }) => {
      const res = await request.post('subscriptions/usage', {
        data: { metric: 'listings', count: 1 },
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      // 200/201 if subscription exists, 404 if not
      expect([200, 201, 404]).toContain(res.status());
    });

    test('rejects usage with invalid count', async ({ request }) => {
      const res = await request.post('subscriptions/usage', {
        data: { metric: 'listings', count: -1 },
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      expect(res.ok()).toBeFalsy();
      expect(res.status()).toBe(400);
    });
  });

  test.describe('GET /subscriptions/billing — Billing history', () => {
    test('returns billing history for authenticated user', async ({ request }) => {
      const res = await request.get('subscriptions/billing', {
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      expect(res.status()).toBe(200);
      const body = await res.json();
      // Response contains subscription, payments, and total
      expect(body).toHaveProperty('payments');
      expect(Array.isArray(body.payments)).toBeTruthy();
    });

    test('supports pagination', async ({ request }) => {
      const res = await request.get('subscriptions/billing', {
        params: { limit: 5, offset: 0 },
        headers: { Authorization: `Bearer ${accessToken}` },
      });

      expect(res.status()).toBe(200);
    });

    test('rejects unauthenticated billing request', async ({ request }) => {
      const res = await request.get('subscriptions/billing');

      expect(res.status()).toBe(401);
    });
  });

  test.describe('PUT /subscriptions/upgrade — Upgrade subscription', () => {
    test('rejects unauthenticated upgrade', async ({ request }) => {
      const res = await request.put('subscriptions/upgrade', {
        data: { newPlanTier: 'AGENT_PRO' },
      });

      expect(res.status()).toBe(401);
    });
  });

  test.describe('DELETE /subscriptions — Cancel subscription', () => {
    test('rejects unauthenticated cancellation', async ({ request }) => {
      const res = await request.delete('subscriptions');

      expect(res.status()).toBe(401);
    });
  });
});
