import { describe, it, expect, beforeEach, vi } from 'vitest';
import ShoppingCart from '@/ShoppingCart.js';

describe('ShoppingCart', () => {
  let cart;
  let mockStorage;

  beforeEach(() => {
    // Мокаем Telegram.WebApp.DeviceStorage
    mockStorage = {
      getItem: vi.fn((key, callback) => {
        const value = localStorage.getItem(key);
        callback(null, value);
      }),
      setItem: vi.fn((key, value) => {
        localStorage.setItem(key, value);
      }),
      deleteItem: vi.fn((key) => {
        localStorage.removeItem(key);
      }),
    };

    global.Telegram = {
      WebApp: {
        DeviceStorage: mockStorage,
      },
    };

    localStorage.clear();
  });

  it('должен инициализироваться с пустой корзиной', async () => {
    cart = new ShoppingCart();
    
    // Даем время на асинхронную загрузку
    await new Promise(resolve => setTimeout(resolve, 10));
    
    expect(cart.getItems()).toEqual([]);
  });

  it('должен загружать данные из storage при инициализации', async () => {
    const savedItems = [
      { productId: 1, productName: 'Product 1', quantity: 2, options: {} },
    ];
    localStorage.setItem('shoppingCart', JSON.stringify(savedItems));

    cart = new ShoppingCart();
    await new Promise(resolve => setTimeout(resolve, 10));

    expect(cart.getItems()).toEqual(savedItems);
  });

  it('должен добавлять товар в корзину', async () => {
    cart = new ShoppingCart();
    await new Promise(resolve => setTimeout(resolve, 10));

    await cart.addItem(1, 'Product 1', 2, { color: 'red' });

    const items = cart.getItems();
    expect(items).toHaveLength(1);
    expect(items[0]).toEqual({
      productId: 1,
      productName: 'Product 1',
      quantity: 2,
      options: { color: 'red' },
    });
  });

  it('должен проверять наличие товара в корзине', async () => {
    cart = new ShoppingCart();
    await new Promise(resolve => setTimeout(resolve, 10));

    await cart.addItem(1, 'Product 1', 1);

    expect(cart.has(1)).toBe(true);
    expect(cart.has(999)).toBe(false);
  });

  it('должен получать товар по ID', async () => {
    cart = new ShoppingCart();
    await new Promise(resolve => setTimeout(resolve, 10));

    await cart.addItem(1, 'Product 1', 2);

    const item = cart.getItem(1);
    expect(item).not.toBeNull();
    expect(item.productId).toBe(1);
    expect(item.productName).toBe('Product 1');

    const notFound = cart.getItem(999);
    expect(notFound).toBeNull();
  });

  it('должен очищать корзину', async () => {
    cart = new ShoppingCart();
    await new Promise(resolve => setTimeout(resolve, 10));

    await cart.addItem(1, 'Product 1', 1);
    cart.clear();

    expect(mockStorage.deleteItem).toHaveBeenCalledWith('shoppingCart');
  });

  it('должен обрабатывать ошибки при загрузке', async () => {
    const consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
    
    mockStorage.getItem = vi.fn((key, callback) => {
      callback(new Error('Storage error'), null);
    });

    cart = new ShoppingCart();
    await new Promise(resolve => setTimeout(resolve, 10));

    expect(cart.getItems()).toEqual([]);
    consoleErrorSpy.mockRestore();
  });
});

