
function reducer(state, { type, name, amount, money }) { //объект action деструктуризируется на три переменных
  if (!state) { //начальная уборка в ларьке:
    return {
      products: {
        пиво: {
          amount: 100,
          price: 30,
        },
        чипсы: {
          amount: 100,
          price: 25,
        },
        сиги: {
          amount: 100,
          price: 35,
        }
      },
      balance: {
        amount: 0
      }
    }
  }
  if (type === 'buy') { //если тип action - КУПИТЬ, то:
    if (amount > state.products[name].amount) {
      alert('You have entered more quantity than is available');
      return {
        ...state,
      }
    }
    if (money < amount * state.products[name].price) {
      alert('You don`t have enought money');
      return {
        ...state,
      }
    }
    if (money > amount * state.products[name].price) {
      alert('You gave more money');
      return {
        ...state,
      }
    }
    let updatedProducts = state.products
    let updatedField = updatedProducts[name];
    updatedField.amount -= amount;
    let updatedBalance = state.balance;
    updatedBalance.amount += +money;
    return {
      ...state, //берем все что было из ассортимента
      products: updatedProducts, //и уменьшаем то, что покупается на количество
      balance: updatedBalance,
    }

  }

  return state; //если мы не поняли, что от нас просят в `action` - оставляем все как есть
}

function createStore(reducer) {
  let state = reducer(undefined, {}) //стартовая инициализация состояния, запуск редьюсера со state === undefined
  let cbs = [];                     //массив подписчиков

  const getState = () => state;            //функция, возвращающая переменную из замыкания

  const subscribe = cb => (cbs.push(cb),   //запоминаем подписчиков в массиве
    () => cbs = cbs.filter(c => c !== cb)); //возвращаем функцию unsubscribe, которая удаляет подписчика из списка

  const dispatch = action => {
    const newState = reducer(state, action); //пробуем запустить редьюсер
    if (newState !== state) { //проверяем, смог ли редьюсер обработать action
      state = newState; //если смог, то обновляем state 
      for (let cb of cbs) cb(); //и запускаем подписчиков
    }
  }

  return {
    getState, //добавление функции getState в результирующий объект
    dispatch,
    subscribe //добавление subscribe в объект
  }
}
const store = createStore(reducer);

//запомнит функцию во внутреннем массиве cbs. 
//она будет запущена при любом успешном dispatch 
const unsubscribe = store.subscribe(() => console.log(store.getState()));

setTimeout(unsubscribe, 10000); //отпишемся через 10 секунд, например

const buyAction = (name, amount, money) => ({ type: 'buy', name, amount, money });

//происходит запуск редьюсера, который создает новый state. 
//dispatch запускает всех подписчиков из массива cbs

function createTable() {
  let state = store.getState();
  let table = document.getElementById('table');
  table.innerHTML = '';
  let headerRow = document.createElement('tr');
  table.append(headerRow);
  let headerName = document.createElement('th');
  headerName.innerText = 'Name';
  headerRow.append(headerName);
  let headerAmount = document.createElement('th');
  headerAmount.innerText = 'Amount';
  headerRow.append(headerAmount);
  let headerPrice = document.createElement('th');
  headerPrice.innerText = 'Price';
  headerRow.append(headerPrice);
  Object.keys(state.products).forEach(key => {
    let row = document.createElement('tr');
    table.append(row);
    let name = document.createElement('td');
    name.innerText = key;
    row.append(name);
    let amount = document.createElement('td');
    amount.innerText = state.products[key].amount;
    row.append(amount);
    let price = document.createElement('td');
    price.innerText = state.products[key].price;
    row.append(price);
  });
}

function createBalance() {
  let state = store.getState();
  let balance = document.getElementById('balance');
  balance.innerHTML = '';
  balance.innerText = `Balance: ${state.balance.amount}`;

}

function createForm() {
  let state = store.getState();
  let form = document.getElementById('form');
  form.innerHTML = '';
  let selectLabel = document.createElement('label');
  selectLabel.innerText = 'Select a product:';
  form.append(selectLabel);
  let select = document.createElement('select');
  form.append(select);
  Object.keys(state.products).forEach(key => {
    let option = document.createElement('option');
    option.innerHTML = key;
    select.append(option);
  });
  let inputLabel = document.createElement('label');
  inputLabel.innerText = 'Enter quantity:';
  form.append(inputLabel);
  let amountInput = document.createElement('input');
  form.append(amountInput);
  let moneyInputLabel = document.createElement('label');
  moneyInputLabel.innerText = 'Enter amount:';
  form.append(moneyInputLabel);
  let moneyInput = document.createElement('input');
  form.append(moneyInput);
  let submitButton = document.createElement('button');
  submitButton.innerText = 'Buy';
  form.append(submitButton);

  submitButton.addEventListener('click', () => {
    store.dispatch(buyAction(select.value, amountInput.value, moneyInput.value));
    init();
  })
}

function init() {
  createTable();
  createBalance();
  createForm();
}
init();
