import { NotFoundException } from '@modules/shared';
import type { IIndustrialListingRepository } from '../../domain/repositories/industrial-listing.repository';
import type { TypesenseIndustrialService } from '../../infrastructure/services/typesense-industrial.service';
import { DeleteIndustrialListingHandler } from '../commands/delete-industrial-listing/delete-industrial-listing.handler';
import { DeleteIndustrialListingCommand } from '../commands/delete-industrial-listing/delete-industrial-listing.command';

describe('DeleteIndustrialListingHandler', () => {
  let handler: DeleteIndustrialListingHandler;
  let mockRepo: { [K in keyof IIndustrialListingRepository]: ReturnType<typeof vi.fn> };
  let mockTypesense: Partial<{ [K in keyof TypesenseIndustrialService]: ReturnType<typeof vi.fn> }>;

  beforeEach(() => {
    mockRepo = {
      findById: vi.fn(),
      findDetailById: vi.fn(),
      save: vi.fn(),
      update: vi.fn().mockResolvedValue(undefined),
      search: vi.fn(),
    };
    mockTypesense = {
      deleteListing: vi.fn().mockResolvedValue(undefined),
      indexListing: vi.fn(),
      indexPark: vi.fn(),
    };
    handler = new DeleteIndustrialListingHandler(mockRepo as any, mockTypesense as any);
  });

  it('soft-deletes an existing listing', async () => {
    const mockEntity = {
      id: 'listing-1',
      status: 'ACTIVE',
      softDelete: vi.fn(),
    };
    mockRepo.findById.mockResolvedValue(mockEntity);

    await handler.execute(new DeleteIndustrialListingCommand('listing-1'));

    expect(mockEntity.softDelete).toHaveBeenCalled();
    expect(mockRepo.update).toHaveBeenCalledWith(mockEntity);
    expect(mockTypesense.deleteListing).toHaveBeenCalledWith('listing-1');
  });

  it('throws NotFoundException when listing does not exist', async () => {
    mockRepo.findById.mockResolvedValue(null);

    await expect(
      handler.execute(new DeleteIndustrialListingCommand('nonexistent')),
    ).rejects.toThrow(NotFoundException);
    expect(mockRepo.update).not.toHaveBeenCalled();
  });

  it('does not fail if Typesense delete rejects', async () => {
    const mockEntity = {
      id: 'listing-1',
      status: 'ACTIVE',
      softDelete: vi.fn(),
    };
    mockRepo.findById.mockResolvedValue(mockEntity);
    mockTypesense.deleteListing!.mockRejectedValue(new Error('Typesense down'));

    await expect(
      handler.execute(new DeleteIndustrialListingCommand('listing-1')),
    ).resolves.toBeUndefined();
  });
});
