import { Test, TestingModule } from '@nestjs/testing';
import { SubscriptionEngineService } from './subscription-engine.service';
import { PrismaService } from '../../prisma/prisma.service';
import { ForbiddenException, NotFoundException } from '@nestjs/common';

describe('SubscriptionEngineService', () => {
  let service: SubscriptionEngineService;
  let prisma: PrismaService;

  const mockPrisma = {
    business: {
      findUnique: jest.fn(),
      update: jest.fn(),
    },
    product: {
      count: jest.fn(),
    },
    customer: {
      count: jest.fn(),
    },
    subscriptionPayment: {
      findUnique: jest.fn(),
      update: jest.fn(),
    },
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        SubscriptionEngineService,
        { provide: PrismaService, useValue: mockPrisma },
      ],
    }).compile();

    service = module.get<SubscriptionEngineService>(SubscriptionEngineService);
    prisma = module.get<PrismaService>(PrismaService);
    jest.clearAllMocks();
  });

  describe('validateRequest', () => {
    it('should throw NotFoundException if business is not found', async () => {
      mockPrisma.business.findUnique.mockResolvedValueOnce(null);

      await expect(service.validateRequest('nonexistent-id')).rejects.toThrow(
        NotFoundException,
      );
    });

    it('should throw ForbiddenException if subscription status is EXPIRED', async () => {
      mockPrisma.business.findUnique.mockResolvedValueOnce({
        id: 'biz-1',
        subscriptionStatus: 'EXPIRED',
        lastCounterReset: new Date(),
      });

      await expect(service.validateRequest('biz-1')).rejects.toThrow(ForbiddenException);
    });

    it('should allow request for active subscription within limits', async () => {
      mockPrisma.business.findUnique.mockResolvedValueOnce({
        id: 'biz-1',
        subscriptionStatus: 'ACTIVE',
        subscriptionPlan: 'PRO',
        subscriptionEnd: new Date(Date.now() + 86400000),
        lastCounterReset: new Date(),
        deliveriesCount: 5,
        apiRequestsCount: 10,
      });

      const allowed = await service.validateRequest('biz-1');
      expect(allowed).toBe(true);
    });
  });

  describe('confirmSubscription', () => {
    it('should update business subscription status to ACTIVE upon payment success', async () => {
      mockPrisma.subscriptionPayment.findUnique.mockResolvedValueOnce({
        id: 'sub-pay-1',
        businessId: 'biz-1',
        status: 'PENDING',
        plan: 'PRO',
        billingCycle: 'monthly',
      });

      mockPrisma.business.findUnique.mockResolvedValueOnce({
        id: 'biz-1',
        subscriptionStatus: 'TRIAL',
        trialEnd: new Date(Date.now() + 86400000),
      });

      await service.confirmSubscription('SUB-123456', 'GW-TX-789');

      expect(mockPrisma.subscriptionPayment.update).toHaveBeenCalledWith(
        expect.objectContaining({
          where: { id: 'sub-pay-1' },
          data: expect.objectContaining({ status: 'SUCCESS' }),
        }),
      );

      expect(mockPrisma.business.update).toHaveBeenCalledWith(
        expect.objectContaining({
          where: { id: 'biz-1' },
          data: expect.objectContaining({
            subscriptionStatus: 'ACTIVE',
            subscriptionPlan: 'PRO',
          }),
        }),
      );
    });
  });
});
