import { Test, TestingModule } from '@nestjs/testing';
import { TicketsService } from './tickets.service';
import { PrismaService } from '../../common/prisma.service';

describe('TicketsService - Offline Validation', () => {
  let service: TicketsService;
  let prisma: PrismaService;

  const mockPrisma = {
    booking: {
      findMany: jest.fn(),
      findUnique: jest.fn(),
    },
    ticket: {
      findUnique: jest.fn(),
      update: jest.fn(),
    },
    gateValidationLog: {
      create: jest.fn(),
    },
  };

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

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

  describe('exportOfflineData', () => {
    it('should export tickets for offline validation', async () => {
      const mockBookings = [
        {
          bookingRef: 'ABC123',
          ticket: { id: 'ticket-1', qrPayload: 'qr-data', validatedAt: null },
          seats: [{ passengerName: 'John Doe', seat: { label: '1A', coach: { label: 'A' } } }],
          status: 'CONFIRMED',
        },
      ];

      mockPrisma.booking.findMany.mockResolvedValue(mockBookings);

      const result = await service.exportOfflineData('trip-1');

      expect(result).toHaveLength(1);
      expect(result[0].bookingRef).toBe('ABC123');
      expect(result[0].passengerName).toBe('John Doe');
    });
  });

  describe('validateOfflineBatch', () => {
    it('should process batch validations successfully', async () => {
      const validations = [
        {
          bookingRef: 'ABC123',
          validatorId: 'validator-1',
          gateId: 'gate-1',
          validatedAt: new Date().toISOString(),
        },
      ];

      mockPrisma.booking.findUnique.mockResolvedValue({ id: 'booking-1' });
      mockPrisma.ticket.findUnique.mockResolvedValue({ id: 'ticket-1', validatedAt: null });
      mockPrisma.ticket.update.mockResolvedValue({});
      mockPrisma.gateValidationLog.create.mockResolvedValue({});

      const result = await service.validateOfflineBatch(validations);

      expect(result.success).toBe(1);
      expect(result.failed).toBe(0);
      expect(result.duplicate).toBe(0);
    });

    it('should detect duplicate validations', async () => {
      const validations = [
        {
          bookingRef: 'ABC123',
          validatorId: 'validator-1',
          validatedAt: new Date().toISOString(),
        },
        {
          bookingRef: 'ABC123',
          validatorId: 'validator-1',
          validatedAt: new Date().toISOString(),
        },
      ];

      mockPrisma.booking.findUnique.mockResolvedValue({ id: 'booking-1' });
      mockPrisma.ticket.findUnique.mockResolvedValue({ id: 'ticket-1', validatedAt: null });
      mockPrisma.ticket.update.mockResolvedValue({});
      mockPrisma.gateValidationLog.create.mockResolvedValue({});

      const result = await service.validateOfflineBatch(validations);

      expect(result.success).toBe(1);
      expect(result.duplicate).toBe(1);
    });

    it('should handle already validated tickets', async () => {
      const validations = [
        {
          bookingRef: 'ABC123',
          validatorId: 'validator-1',
          validatedAt: new Date().toISOString(),
        },
      ];

      mockPrisma.booking.findUnique.mockResolvedValue({ id: 'booking-1' });
      mockPrisma.ticket.findUnique.mockResolvedValue({
        id: 'ticket-1',
        validatedAt: new Date(),
      });

      const result = await service.validateOfflineBatch(validations);

      expect(result.duplicate).toBe(1);
      expect(result.success).toBe(0);
    });
  });
});
