import { UpdateSavedSearchCommand } from '../commands/update-saved-search/update-saved-search.command';
import { UpdateSavedSearchHandler } from '../commands/update-saved-search/update-saved-search.handler';

describe('UpdateSavedSearchHandler', () => {
  let handler: UpdateSavedSearchHandler;
  let mockPrisma: any;
  let mockLogger: { log: ReturnType<typeof vi.fn>; warn: ReturnType<typeof vi.fn> };

  const existingSearch = {
    id: 'saved-1',
    userId: 'user-1',
    name: 'Original Name',
    filters: { district: 'Quan 7' },
    alertEnabled: true,
    lastAlertAt: null,
    createdAt: new Date('2026-01-01'),
  };

  beforeEach(() => {
    mockPrisma = {
      savedSearch: {
        findUnique: vi.fn(),
        update: vi.fn(),
      },
    };
    mockLogger = { log: vi.fn(), warn: vi.fn() };

    handler = new UpdateSavedSearchHandler(mockPrisma, mockLogger as any);
  });

  it('updates the name of a saved search', async () => {
    mockPrisma.savedSearch.findUnique.mockResolvedValue(existingSearch);
    mockPrisma.savedSearch.update.mockResolvedValue({
      ...existingSearch,
      name: 'New Name',
    });

    const command = new UpdateSavedSearchCommand('saved-1', 'user-1', 'New Name');
    const result = await handler.execute(command);

    expect(result.name).toBe('New Name');
    expect(mockPrisma.savedSearch.update).toHaveBeenCalledWith({
      where: { id: 'saved-1' },
      data: { name: 'New Name' },
    });
  });

  it('updates alertEnabled', async () => {
    mockPrisma.savedSearch.findUnique.mockResolvedValue(existingSearch);
    mockPrisma.savedSearch.update.mockResolvedValue({
      ...existingSearch,
      alertEnabled: false,
    });

    const command = new UpdateSavedSearchCommand('saved-1', 'user-1', undefined, undefined, false);
    const result = await handler.execute(command);

    expect(result.alertEnabled).toBe(false);
  });

  it('throws NotFoundException when saved search does not exist', async () => {
    mockPrisma.savedSearch.findUnique.mockResolvedValue(null);

    const command = new UpdateSavedSearchCommand('non-existent', 'user-1', 'New Name');
    await expect(handler.execute(command)).rejects.toThrow();
  });

  it('throws ForbiddenException when user does not own the saved search', async () => {
    mockPrisma.savedSearch.findUnique.mockResolvedValue({
      ...existingSearch,
      userId: 'other-user',
    });

    const command = new UpdateSavedSearchCommand('saved-1', 'user-1', 'New Name');
    await expect(handler.execute(command)).rejects.toThrow('Bạn không có quyền cập nhật tìm kiếm này');
  });

  it('throws ValidationException when name is empty', async () => {
    mockPrisma.savedSearch.findUnique.mockResolvedValue(existingSearch);

    const command = new UpdateSavedSearchCommand('saved-1', 'user-1', '');
    await expect(handler.execute(command)).rejects.toThrow('Tên tìm kiếm không được để trống');
  });
});
