import { Test, TestingModule } from '@nestjs/testing';
import { WhatsAppBotEngine } from './whatsapp-bot.engine';
import { PrismaService } from '../../../prisma/prisma.service';
import { WhatsAppSessionService } from './whatsapp-session.service';
import { ProductsService } from '../../commerce/services/products.service';
import { CartsService } from '../../commerce/services/carts.service';
import { OrdersService } from '../../commerce/services/orders.service';

describe('WhatsAppBotEngine - Product Search', () => {
  let botEngine: WhatsAppBotEngine;
  let productsService: ProductsService;
  let sessionService: WhatsAppSessionService;

  const mockPrisma = {
    customer: {
      findFirst: jest.fn(),
      create: jest.fn(),
    },
    product: {
      findMany: jest.fn(),
      findUnique: jest.fn(),
    },
    category: {
      findMany: jest.fn(),
      findUnique: jest.fn(),
    },
    business: {
      findUnique: jest.fn(),
    },
    session: {
      findFirst: jest.fn(),
    },
  };

  const mockSessionService = {
    getOrCreateSession: jest.fn(),
    updateStep: jest.fn(),
    updateSessionData: jest.fn(),
    clearSession: jest.fn(),
  };

  const mockProductsService = {
    listProducts: jest.fn(),
    listCategories: jest.fn(),
    getProduct: jest.fn(),
  };

  const mockCartsService = {
    getOrCreateCart: jest.fn(),
    addToCart: jest.fn(),
  };

  const mockOrdersService = {
    createOrder: jest.fn(),
  };

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      providers: [
        WhatsAppBotEngine,
        { provide: PrismaService, useValue: mockPrisma },
        { provide: WhatsAppSessionService, useValue: mockSessionService },
        { provide: ProductsService, useValue: mockProductsService },
        { provide: CartsService, useValue: mockCartsService },
        { provide: OrdersService, useValue: mockOrdersService },
      ],
    }).compile();

    botEngine = module.get<WhatsAppBotEngine>(WhatsAppBotEngine);
    productsService = module.get<ProductsService>(ProductsService);
    sessionService = module.get<WhatsAppSessionService>(WhatsAppSessionService);
    jest.clearAllMocks();
  });

  it('should find products when user searches SC301 in SEARCH_PRODUCTS step', async () => {
    mockPrisma.customer.findFirst.mockResolvedValue({ id: 'c-1', whatsappNumber: '263771234567' });
    mockSessionService.getOrCreateSession.mockResolvedValue({
      id: 's-1',
      businessId: 'biz-1',
      currentStep: 'SEARCH_PRODUCTS',
      sessionDataJson: '{}',
    });
    mockProductsService.listProducts.mockResolvedValue([
      { id: 'p-1', name: 'Seed Co SC 301 Maize Seed', sku: 'SC 301', price: 35 },
    ]);

    const res = await botEngine.processMessage('biz-1', '263771234567', 'SC301');

    expect(mockProductsService.listProducts).toHaveBeenCalledWith('biz-1', 'SC301');
    expect(res.text).toContain('Seed Co SC 301 Maize Seed');
    expect(res.payload?.type).toBe('product_carousel');
    expect(mockSessionService.updateStep).toHaveBeenCalledWith('s-1', 'BROWSE_PRODUCTS');
  });

  it('should find products when user searches SC 301 with spaces', async () => {
    mockPrisma.customer.findFirst.mockResolvedValue({ id: 'c-1', whatsappNumber: '263771234567' });
    mockSessionService.getOrCreateSession.mockResolvedValue({
      id: 's-1',
      businessId: 'biz-1',
      currentStep: 'SEARCH_PRODUCTS',
      sessionDataJson: '{}',
    });
    mockProductsService.listProducts.mockResolvedValue([
      { id: 'p-1', name: 'Seed Co SC 301 Maize Seed', sku: 'SC301', price: 35 },
    ]);

    const res = await botEngine.processMessage('biz-1', '263771234567', 'SC 301');

    expect(mockProductsService.listProducts).toHaveBeenCalledWith('biz-1', 'SC 301');
    expect(res.text).toContain('Seed Co SC 301 Maize Seed');
  });

  it('should intercept global search command "search SC301" from any step', async () => {
    mockPrisma.customer.findFirst.mockResolvedValue({ id: 'c-1', whatsappNumber: '263771234567' });
    mockSessionService.getOrCreateSession.mockResolvedValue({
      id: 's-1',
      businessId: 'biz-1',
      currentStep: 'SUPPORT',
      sessionDataJson: '{}',
    });
    mockProductsService.listProducts.mockResolvedValue([
      { id: 'p-1', name: 'Seed Co SC 301 Maize Seed', sku: 'SC 301', price: 35 },
    ]);

    const res = await botEngine.processMessage('biz-1', '263771234567', 'search SC301');

    expect(mockProductsService.listProducts).toHaveBeenCalledWith('biz-1', 'SC301');
    expect(res.text).toContain('Seed Co SC 301 Maize Seed');
  });

  it('should directly search when user enters SC 301 at the welcome menu', async () => {
    mockPrisma.customer.findFirst.mockResolvedValue({ id: 'c-1', whatsappNumber: '263771234567' });
    mockSessionService.getOrCreateSession.mockResolvedValue({
      id: 's-1',
      businessId: 'biz-1',
      currentStep: 'WELCOME',
      sessionDataJson: '{}',
    });
    mockProductsService.listProducts.mockResolvedValue([
      { id: 'p-1', name: 'Seed Co SC 301 Maize Seed', sku: 'SC 301', price: 35 },
    ]);

    const res = await botEngine.processMessage('biz-1', '263771234567', 'SC 301');

    expect(mockProductsService.listProducts).toHaveBeenCalledWith('biz-1', 'SC 301');
    expect(res.text).toContain('Seed Co SC 301 Maize Seed');
  });
});
