import { ConfirmBankTransferCommand } from '../../../application/commands/confirm-bank-transfer/confirm-bank-transfer.command';
import { AdminPaymentsController } from '../admin-payments.controller';

describe('AdminPaymentsController', () => {
  let controller: AdminPaymentsController;
  let mockCommandBus: { execute: ReturnType<typeof vi.fn> };

  const mockAdmin = { sub: 'admin-1', phone: '0901234567', role: 'ADMIN' } as any;

  beforeEach(() => {
    mockCommandBus = { execute: vi.fn() };
    controller = new AdminPaymentsController(mockCommandBus as any);
  });

  describe('POST /admin/payments/:id/confirm-transfer', () => {
    it('dispatches ConfirmBankTransferCommand with admin sub + bankReference', async () => {
      const expected = {
        paymentId: 'pay-1',
        status: 'COMPLETED',
        confirmedBy: 'admin-1',
      };
      mockCommandBus.execute.mockResolvedValue(expected);

      const result = await controller.confirmBankTransfer(
        'pay-1',
        { bankReference: 'FT123456' } as any,
        mockAdmin,
      );

      expect(mockCommandBus.execute).toHaveBeenCalledWith(
        expect.any(ConfirmBankTransferCommand),
      );
      const cmd = mockCommandBus.execute.mock.calls[0]![0] as ConfirmBankTransferCommand;
      expect(cmd.paymentId).toBe('pay-1');
      expect(cmd.confirmedBy).toBe('admin-1');
      expect(cmd.bankReference).toBe('FT123456');
      expect(result).toEqual(expected);
    });

    it('supports omitted bankReference', async () => {
      mockCommandBus.execute.mockResolvedValue({
        paymentId: 'pay-2',
        status: 'COMPLETED',
        confirmedBy: 'admin-1',
      });

      await controller.confirmBankTransfer('pay-2', {} as any, mockAdmin);

      const cmd = mockCommandBus.execute.mock.calls[0]![0] as ConfirmBankTransferCommand;
      expect(cmd.paymentId).toBe('pay-2');
      expect(cmd.confirmedBy).toBe('admin-1');
      expect(cmd.bankReference).toBeUndefined();
    });

    it('propagates errors from the command bus', async () => {
      mockCommandBus.execute.mockRejectedValue(new Error('validation failed'));

      await expect(
        controller.confirmBankTransfer('pay-3', {} as any, mockAdmin),
      ).rejects.toThrow('validation failed');
    });
  });
});
