const delay = ms => new Promise(ok => setTimeout(() => ok(ms), ms))

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 => {
    if (typeof action === 'function') { //если action - не объект, а функция
      return action(dispatch, getState) //запускаем эту функцию и даем ей dispatch и getState для работы
    }
    const newState = reducer(state, action) //пробуем запустить редьюсер
    if (newState !== state) { //проверяем, смог ли редьюсер обработать action
      state = newState //если смог, то обновляем state 

      /*state = {
          ...state,
          ...newState
      }*/ //если смог, то обновляем state 
      for (let cb of cbs) cb() //и запускаем подписчиков
    }
  }

  return {
    getState, //добавление функции getState в результирующий объект
    dispatch,
    subscribe //добавление subscribe в объект
  }
}

function promiseReducer(state = {}, { promiseName, type, status, payload, error }) {
  if (type === 'PROMISE') {
    return {
      ...state,
      [promiseName]: { status, payload, error }
    }
  }
  return state
}

const actionPending = promiseName => ({ promiseName, type: 'PROMISE', status: 'PENDING' })
const actionFulfilled = (promiseName, payload) => ({ promiseName, type: 'PROMISE', status: 'FULFILLED', payload })
const actionRejected = (promiseName, error) => ({ promiseName, type: 'PROMISE', status: 'REJECTED', error })

const actionPromise = (promiseName, promise) =>
  async dispatch => {

    dispatch(actionPending(promiseName)) //сигнализируем redux, что промис начался
    try {
      const payload = await promise //ожидаем промиса
      dispatch(actionFulfilled(promiseName, payload)) //сигнализируем redux, что промис успешно выполнен
      return payload //в месте запуска store.dispatch с этим thunk можно так же получить результат промиса
    }
    catch (error) {
      dispatch(actionRejected(promiseName, error)) //в случае ошибки - сигнализируем redux, что промис несложился
    }
  }

// const store = createStore(promiseReducer)
// store.subscribe(() => console.log(store.getState()))

// store.dispatch(actionPromise('delay', delay(1000)))
// store.dispatch(actionPromise('luke', fetch("https://swapi.dev/api/people/1").then(res => res.json())))
// store.dispatch(actionPromise('tatooine', fetch("https://swapi.dev/api/planets/1").then(res => res.json())))
//по итогу должен получится какой-то такой state:
/*
{
    delay: {status: 'FULFILLED', payload: 1000, error: undefined},
    luke: {status: 'FULFILLED', payload: { ..... траливали про люка}, error: undefined},
    tatooine: {status: 'FULFILLED', payload: { ..... траливали про планету татуин}, error: undefined},
}
*/

/* authReducer
Этот редьюсер предназначен для хранения и обработки состояния залогиненности пользователя. У него бывает два вида состояний:
Залогинен. state вида: {token: "jwt токен", payload: {.....раскодированная инфа из токена}}
Незалогинен. state вида: {} (пустой объект)
Редьюсер обрабатывает два типа экшонов:
AUTH_LOGIN. Логинимся. Редьюсер должен попытаться раскодировать токен, и если это получилось, вернуть новый стейт вида {token, payload} Если токен не удалось раскодировать, вернуть пустой объект (т. е. разлогиниться)
AUTH_LOGOUT. Разлогиниваемся. Возвращаем пустой объект.
Проверочный код (и экшенкриейторы бонусом):*/


function jwtDecode(token) {
  let result;
  try {
    let secondPartToken = token.split('.')[1];
    result = JSON.parse(atob(secondPartToken));
  } catch (e) {
  }

  return result;
}

function authReducer(state = {}, { type, token }) {
  if (type === 'AUTH_LOGIN') {
    payload = jwtDecode(token)
    console.log(payload)
    if (payload) return { token, payload }
  }

  if (type === 'AUTH_LOGOUT') return {}

  return state
}

const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })
const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })




// const store = createStore(authReducer)
// store.subscribe(() => console.log(store.getState()))

// store.dispatch(actionAuthLogout())
// store.dispatch(actionAuthLogin(token))

/*{
    token: "eyJhbGc.....", 
    payload: {
      "sub": {
        "id": "6377e133b74e1f5f2ec1c125",
        "login": "test5",
        "acl": [
          "6377e133b74e1f5f2ec1c125",
          "user"
        ]
      },
      "iat": 1668812458
    }
}*/
//store.dispatch(actionAuthLogout()) // {}


/*cartReducer
Редьюсер, который хранит состояние корзины во время серфинга по интернет-магазину. Похож на редьюсер ларька, только работает немного наоборот - в то время как в ларьке товар уменьшается, тут он добавляется.

Состояние:
{
    idТовара1: {count: количество1, good: {....инфа про товар с бэкэнда, включая цену, описание и картинки}},
    idТовара2: {count: количество2, good: {....инфа про товар с бэкэнда, включая цену, описание и картинки}},
}

Типы экшенов
*/
// Добавление товара. Должен добавлять новый ключ в state, или обновлять, если ключа в state ранее не было, увеличивая количество
const actionCartAdd = (good, count = 1) => ({ type: 'CART_ADD', count, good })

// Уменьшение количества товара. Должен уменьшать количество товара в state, или удалять его если количество будет 0 или отрицательным
const actionCartSub = (good, count = 1) => ({ type: 'CART_SUB', count, good })

// Удаление товара. Должен удалять ключ из state
const actionCartDel = (good) => ({ type: 'CART_DEL', good })

// Задание количества товара. В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху (или создает новый ключ, если в корзине товара не было). Если count 0 или отрицательное число - удаляем ключ из корзины;
const actionCartSet = (good, count = 1) => ({ type: 'CART_SET', count, good })

// Очистка корзины. state должен стать пустым объектом {}
const actionCartClear = () => ({ type: 'CART_CLEAR' })

/*
Проверочный код
Наличие good как ключа в state немного избыточно - для оформления заказа достаточно id и количества. Однако это позволит хранить в редьюсере всю нужную информацию, например, для отображения страницы корзины без лишних запросов на сервер. На странице корзины обычно есть и описание, и цена, и фоточки.
Проверочный код ниже использует в качестве id более наглядные вещи.
*/

function cartReducer(state = {}, { type, count, good }) {
  if (type === 'CART_ADD') {
    if (good._id in state) {
      return {
        ...state,
        [good._id]: {
          good,
          count: state[good._id].count + count
        }
      }
    } else {
      return {
        ...state,
        [good._id]: {
          good,
          count
        }
      }
    }
  }
  if (type === 'CART_SUB') {
    let result = {}
    if (good._id in state) {
      if ((state[good._id].count - count) <= 0) {
        newState = { ...state }
        delete newState[good._id]
        return newState
      } else {
        return {
          ...state,
          [good._id]: {
            good,
            count: state[good._id].count - count
          }
        }
      }
    }
  }

  if (type === 'CART_DEL') {
    let newState = { ...state }
    delete newState[good._id]
    return newState
  }
  // Задание количества товара. В отличие от добавления и уменьшения, не учитывает того количества, которое уже было в корзине, а тупо назначает количество поверху (или создает новый ключ, если в корзине товара не было). Если count 0 или отрицательное число - удаляем ключ из корзины;
  if (type === 'CART_SET') {
    if (good._id in state && count <= 0) {
      let newState = { ...state }
      delete newState[good._id]
      return newState
    } else {
      let newState = {
        ...state,
        [good._id]: {
          good,
          count
        }
      }
      return newState
    }
  }
  if (type === 'CART_CLEAR') return {}
  return state
}

function combineReducers(reducers) {
  function totalReducer(state = {}, action) {
    const newTotalState = {}
    for (const [reducerName, reducer] of Object.entries(reducers)) {
      const newSubState = reducer(state[reducerName], action)
      if (newSubState !== state[reducerName]) {
        newTotalState[reducerName] = newSubState
      }
    }
    if (Object.keys(newTotalState).length) {
      return { ...state, ...newTotalState }
    }
    return state
  }

  return totalReducer
}

const reducers = {
  promise: promiseReducer, //допилить много имен для многих промисо
  auth: authReducer,     //часть предыдущего ДЗ
  cart: cartReducer,     //часть предыдущего ДЗ
}

const totalReducer = combineReducers(reducers)

function localStoredReducer(originalReducer, localStorageKey) {
  let counter = 0
  function wrapper(state, action) {
    if (counter === 0) {
      counter++
      if (localStorage[localStorageKey]) {
        let result = JSON.parse(localStorage[localStorageKey])
        if (result) return result
      }
    } else {
      let result = originalReducer(state, action)
      localStorage[localStorageKey] = JSON.stringify(result)
      return result
    }
  }
  return wrapper
}

const store = createStore(localStoredReducer(totalReducer, "state")) //не забудьте combineReducers если он у вас уже есть

store.subscribe(() => console.log(store.getState()))

const actionRootCats = () => actionPromise("RootCats", gqlRootCats())
store.dispatch(actionRootCats())



store.subscribe(() => {
  let result = store.getState().promise.RootCats.payload
  if (result) {
    aside.innerHTML = ""
    for (let { _id, name } of result) {
      aside.innerHTML += `<a href='#/category/${_id}'>${name}</a>`
    }
  }
})



const actionCategoryGoodsAndSubCategoryGoods = (_id) => actionPromise("CategoryGoodsAndSubCategoryGoods", gqlCategoryGoodsAndSubCategoryGoods(_id))

store.dispatch(actionCategoryGoodsAndSubCategoryGoods('62c94b10b74e1f5f2ec1a0dd'))

store.subscribe(() => {
  if (location.hash === '') {
    const { status, payload, error } = store.getState().promise.CategoryGoodsAndSubCategoryGoods
    if (status === 'PENDING') {
      main.innerHTML = `<img src='giphy.gif'/>`
    }
    if (status === 'FULFILLED') {
      if (payload) categotyToMain(payload)
    }
    if (status === 'REJECTED') {
      main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: <a href="mailto:mail@example.com">blablatest123@gmail.com</a>`
    }
  }
})

function categotyToMain(result) {
  main.innerHTML = ""
  let breadcrumbsContainer = document.createElement('div')
  main.append(breadcrumbsContainer)
  breadcrumbsContainer.classList.add('breadcrumbsContainer')
  let breadcrumbsHome = document.createElement('a')
  breadcrumbsContainer.append(breadcrumbsHome)
  breadcrumbsHome.innerText = 'Mystore.com'
  breadcrumbsHome.href = location.origin + location.pathname
  if (result.parent){    
  breadcrumbsContainer.innerHTML += `<div>></div><div>...</div><div>></div><a href='#/category/${result.parent._id}'>${result.parent.name}</a>`
  }
  let h1 = document.createElement('h1')
  h1.innerText = result.name
  main.append(h1)
  if (result.subCategories && result.subCategories.length>0){
    const containerSubcategoryLink = document.createElement('div')
    containerSubcategoryLink.classList.add('containerSubcategoryLink')
    main.append(containerSubcategoryLink)
    for(const {_id, name} of result.subCategories){
      console.log(name)
      let subcategoryLink = document.createElement('a')
      containerSubcategoryLink.append(subcategoryLink)
      subcategoryLink.href = `#/category/${_id}`
      subcategoryLink.classList.add('subcategoryLink')
      subcategoryLink.innerText = name      
    }
  }

if (!result.goods){
  let emptyCategoryMessage = document.createElement('div')
  main.append(emptyCategoryMessage)
  emptyCategoryMessage.innerText = 'В этой категории пока нет товаров :('
  return
}


  for (let { _id, name, images, price} of result?.goods) {

    let card = document.createElement('a')
    card.id = _id
    card.href = `#/good/${_id}`
    card.classList.add('card')
    main.append(card)
    let cardImgWrapper = document.createElement('div')
    cardImgWrapper.classList.add('cardImgWrapper')
    card.append(cardImgWrapper)
    let cardImg = document.createElement('img')
    cardImg.classList.add('cardImg')
    cardImgWrapper.append(cardImg)
    if (images.length>0){
    let { url } = images[0]
    cardImg.src = hostname + url
    } else{
      cardImg.src = 'https://lukachi.com.ua/source/default-image.jpg'
    }
    let cardName = document.createElement('h2')
    cardName.classList.add('cardName')
    cardName.innerText = name
    card.append(cardName)
    let cardPrice = document.createElement('div')
    cardPrice.classList.add('cardPrice')
    cardPrice.innerText = price + " грн"
    card.append(cardPrice)

  }
}

let hostname = 'http://shop-roles.node.ed.asmer.org.ua/'

// store.subscribe(() => {
//   let result = store.getState().promise.CategoryGoodsAndSubCategoryGoods?.payload
//   const [, route, _id] = location.hash.split('/')
//   if (result && route === "category") {
//     categotyToMain(result)
//   }
// })

store.subscribe(() => {
  const [, route, _id] = location.hash.split('/')
  if (route !== "category") return
  const { status, payload, error } = store.getState().promise.CategoryGoodsAndSubCategoryGoods
  if (status === 'PENDING') {
    main.innerHTML = `<img src='giphy.gif'/>`
  }
  if (status === 'FULFILLED' && payload) {
    categotyToMain(payload)
  }
  if (status === 'REJECTED') {
    main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: <a href="mailto:mail@example.com">blablatest123@gmail.com</a>`
  }
})

// store.subscribe(() => {
//   let result = store.getState().promise.OneGoodWithDescriptionAndImages?.payload
//   const [, route, _id] = location.hash.split('/')
//   if (result && route === "good") {
//     main.innerHTML = ""
//     let h1 = document.createElement('h1')
//     h1.innerText = result.name
//     main.append(h1)
//     let imgSlider = document.createElement('div')
//     imgSlider.classList.add('imgSlider')
//     main.append(imgSlider)
//     for (let { url } of result.images) {
//       imgSlider.innerHTML += `<img class="sliderImg" src="${hostname + url}"></img>`
//     }

//     let asideDesriptionPriceCard = document.createElement('div')
//     asideDesriptionPriceCard.classList.add('asideDesriptionPriceCard')
//     main.append(asideDesriptionPriceCard)

//     let goodPrice = document.createElement('div')
//     goodPrice.classList.add('goodPrice')
//     goodPrice.innerText = result.price + ' грн'
//     asideDesriptionPriceCard.append(goodPrice)

//     let goodCountInput = document.createElement('input')
//     goodCountInput.classList.add('goodCountInput')
//     goodCountInput.type = 'number'
//     goodCountInput.min = 1
//     goodCountInput.value = 1
//     asideDesriptionPriceCard.append(goodCountInput)

//     let goodButtonAddToCart = document.createElement('a')
//     goodButtonAddToCart.classList.add('goodButtonAddToCart')
//     goodButtonAddToCart.innerText = 'В КОРЗИНУ'
//     goodButtonAddToCart.onclick = () => store.dispatch(actionCartAdd(result, +goodCountInput.value))
//     asideDesriptionPriceCard.append(goodButtonAddToCart)

//     let description = document.createElement('div')
//     description.classList.add('description')
//     description.innerText = result.description
//     asideDesriptionPriceCard.append(description)
//   }
// })

store.subscribe(() => {
  const [, route, _id] = location.hash.split('/')
  if (route !== "good") return
  const { status, payload, error } = store.getState().promise.OneGoodWithDescriptionAndImages
  if (status === 'PENDING') {
    main.innerHTML = `<img src='giphy.gif'/>`
  }
  if (status === 'FULFILLED' && payload) {
    main.innerHTML = ""
    let h1 = document.createElement('h1')
    h1.innerText = payload.name
    main.append(h1)
    let imgSlider = document.createElement('div')
    imgSlider.classList.add('imgSlider')
    main.append(imgSlider)
    for (let { url } of payload.images) {
      imgSlider.innerHTML += `<img class="sliderImg" src="${hostname + url}"></img>`
    }

    let asideDesriptionPriceCard = document.createElement('div')
    asideDesriptionPriceCard.classList.add('asideDesriptionPriceCard')
    main.append(asideDesriptionPriceCard)

    let goodPrice = document.createElement('div')
    goodPrice.classList.add('goodPrice')
    goodPrice.innerText = payload.price + ' грн'
    asideDesriptionPriceCard.append(goodPrice)

    let goodCountInput = document.createElement('input')
    goodCountInput.classList.add('goodCountInput')
    goodCountInput.type = 'number'
    goodCountInput.min = 1
    goodCountInput.value = 1
    asideDesriptionPriceCard.append(goodCountInput)

    let goodButtonAddToCart = document.createElement('a')
    goodButtonAddToCart.classList.add('goodButtonAddToCart')
    goodButtonAddToCart.innerText = 'В КОРЗИНУ'
    goodButtonAddToCart.onclick = () => store.dispatch(actionCartAdd(payload, +goodCountInput.value))
    asideDesriptionPriceCard.append(goodButtonAddToCart)

    let description = document.createElement('div')
    description.classList.add('description')
    description.innerText = payload.description
    asideDesriptionPriceCard.append(description)
  }  
  if (status === 'REJECTED') {
    main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: <a href="mailto:mail@example.com">blablatest123@gmail.com</a>`
  }
})

const actionOneGoodWithDescriptionAndImages = (_id) => actionPromise("OneGoodWithDescriptionAndImages", gqlOneGoodWithDescriptionAndImages(_id))


store.subscribe(() => {
  let result = 0
  let arrResult = Object.values(store.getState().cart)
  for (let { count } of arrResult) {
    result += count
  }
  cartIcon.innerText = result
})

store.subscribe(() => {
  let arrResult = Object.values(store.getState().cart)
  const [, route, _id] = location.hash.split('/')
  if (arrResult && route === "cart") {
    cartPageAdd()
  }
})


window.onhashchange = () => {
  const [, route, _id] = location.hash.split('/')

  const routes = {
    category() {
      store.dispatch(actionCategoryGoodsAndSubCategoryGoods(_id))

    },
    good() {
      store.dispatch(actionOneGoodWithDescriptionAndImages(_id))
      // тут был store.dispatch goodById
      console.log('good', _id)
    },
    // login() {
    //   console.log('А ТУТ ЩА ДОЛЖНА БЫТЬ ФОРМА ЛОГИНА')
    //   //нарисовать форму логина, которая по нажатию кнопки Login делает store.dispatch(actionFullLogin(login, password))
    // },
    // register() {
    //   //нарисовать форму регистрации, которая по нажатию кнопки Login делает store.dispatch(actionFullRegister(login, password))
    // },
    cart() {
      cartPageAdd()
    },
    orders() {
      store.dispatch(actionOrderFind())
    }
  }
  if (route in routes) {
    routes[route]()
  }
}

function cartPageAdd() {
  let arrResult = Object.values(store.getState().cart)
  const [, route, _id] = location.hash.split('/')
  if (arrResult && route === "cart") {
    main.innerHTML = ""
    let h1 = document.createElement('h1')
    h1.innerText = "Оформление заказа"
    main.append(h1)
    let orderTable = document.createElement('table')
    main.append(orderTable)
    orderTable.classList.add('table_price')
    let orderTableBody = document.createElement('tbody')
    orderTable.append(orderTableBody)
    
    let firstTr = document.createElement('tr')
    orderTableBody.append(firstTr)
    firstTr.innerHTML = `<th></th><th>Название товара</th><th>Цена шт.</th><th>Количество</th><th>Итого</th><th></th>`
    let counter = 1
    let summ = 0
    for (let { good, count } of arrResult) {
      console.log(count)
      let trGood = document.createElement('tr')
      orderTableBody.append(trGood)
      trGood.innerHTML = `
        <td>${counter}</td>
        <td>${good.name}</td>
        <td>${good.price}</td>`

        let tdInput = document.createElement('td')
        trGood.append(tdInput)        
        let inputCount = document.createElement('input')
        inputCount.type = 'number'
        inputCount.min = 1
        inputCount.value = count
        inputCount.oninput = () => store.dispatch(actionCartSet(good, +inputCount.value))
        tdInput.append(inputCount)

        let tdSummGood = document.createElement('td')
        trGood.append(tdSummGood)
        tdSummGood.innerText = count * good.price

        let tdDelete = document.createElement('td')
        trGood.append(tdDelete)

        let deleteButton = document.createElement('button')
        tdDelete.append(deleteButton)
        deleteButton.classList.add('deleteButton')
        deleteButton.innerText = 'удалить'
        deleteButton.onclick = () => store.dispatch(actionCartDel(good))

        
        //НЕ РАБОТАЕТ!? trGood.innerHTML += `<td>${count * good.price}</td>`

      counter += 1
      summ += count * good.price
    }
    let trSummTotal = document.createElement('tr')
    orderTableBody.append(trSummTotal)

    let tdColspan = document.createElement('td')
    trSummTotal.append(tdColspan)
    tdColspan.colSpan = 4

    let tdSummTotal = document.createElement('td')
    trSummTotal.append(tdSummTotal)
    tdSummTotal.innerText = summ +'грн'
    tdSummTotal.classList.add('tdSumm')

    let tdDeleteTotal = document.createElement('td')
    trSummTotal.append(tdDeleteTotal)

    let DeleteTotalButton = document.createElement('button')
    tdDeleteTotal.append(DeleteTotalButton)
    DeleteTotalButton.innerText = 'ОЧИСТИТЬ КОРЗИНУ'
    DeleteTotalButton.onclick = () => store.dispatch(actionCartClear())
    


    //orderTableBody.innerHTML += `<tr><td colspan="4"></td><td class="tdSumm">${summ} грн</td></tr>`
    let addOrder = document.createElement('div')
    addOrder.classList.add('addOrder')
    addOrder.innerText = "ОФОРМИТЬ ЗАКАЗ"
    main.append(addOrder)
    let arrGoods = Object.values(store.getState().cart).map(({ count, good: { _id } }) => { return { count, good: { _id } } })
    addOrder.onclick = () => {
      store.dispatch(actionFullAddOrder(arrGoods))
    }
  }
}

const actionAddOrder = (arrGoods) => {
  return actionPromise("orderUpsert", OrderUpsert2(arrGoods))
}




const actionFullAddOrder = (arrGoods) =>
  async dispatch => {
    await dispatch(actionAddOrder(arrGoods))
    dispatch(actionCartClear())
    location.hash = '#/orders'
  }


const actionLogin = (login, password) => {
  return actionPromise("logAndPass", gqllogin(login, password))
}

const actionRegistration = (login, password) => {
  return actionPromise("newUser", gqlUserAdd(login, password))
}


const actionFullLogin = (login, password) =>
  async dispatch => {
    //dispatch возвращает то, что вернул thunk, возвращаемый actionLogin, а там промис, 
    //так как actionPromise возвращает асинхронную функцию
    const token = await dispatch(actionLogin(login, password))
    //проверьте что token - строка и отдайте его в actionAuthLogin
    if (typeof token === 'string')
      store.dispatch(actionAuthLogin(token))
  }

const actionFullRegistration = (login, password) =>
  async dispatch => {
    const userAddPromis = await dispatch(actionRegistration(login, password))
    if (userAddPromis) store.dispatch(actionFullLogin(login, password))
    //dispatch возвращает то, что вернул thunk, возвращаемый actionLogin, а там промис, 
    //так как actionPromise возвращает асинхронную функцию
    //const token = await dispatch(actionLogin(login, password))
    //проверьте что token - строка и отдайте его в actionAuthLogin
    //if (typeof token === 'string')
    //  store.dispatch(actionAuthLogin(token))
  }

const actionOrderFind = () =>
  actionPromise("OrderFind", gqlOrderFind())

function LoginFormFunc(parent, passOpenDefault = open) {
  function Password(parent, open) {

    const inputPass = document.createElement('input')
    parent.append(inputPass)
    const checkboxPass = document.createElement('input')
    checkboxPass.type = 'checkbox'
    parent.append(checkboxPass)

    this.setValue = (value) => {
      inputPass.value = value
      if (typeof this.onChange === 'function') this.onChange(this.getValue()) // запускается по событию oninput в поле ввода, передает текст в колбэк
    }      //задает значение
    this.getValue = () => inputPass.value                   //читает значение
    this.setOpen = (open) => {
      if (open) {
        checkboxPass.checked = true
        inputPass.type = "text"
      }
      if (!open) {
        checkboxPass.checked = false
        inputPass.type = "password"
      }
      if (typeof this.onOpenChange === 'function') this.onOpenChange(this.getOpen()) // запускается по изменению состояния открытости пароля
    } //задает открытость текста в поле ввода
    this.getOpen = () => checkboxPass.checked //читает открытость текста в поле ввода

    this.setOpen(open)
    inputPass.oninput = () => this.setValue(this.getValue())
    checkboxPass.oninput = () => this.setOpen(this.getOpen())

  }

  const LoginForm = document.createElement('div')
  parent.append(LoginForm)

  const inputLogin = document.createElement('input')
  LoginForm.append(inputLogin)

  let p = new Password(LoginForm, passOpenDefault)

  const inputButton = document.createElement('input')
  inputButton.type = 'button'
  inputButton.value = 'войти'
  inputButton.id = 'signIn'
  LoginForm.append(inputButton)
  inputButton.disabled = true

  const newUserAddButton = document.createElement('input')
  newUserAddButton.type = 'button'
  newUserAddButton.value = 'зарегистрироваться'
  newUserAddButton.id = 'register'
  LoginForm.append(newUserAddButton)

  p.onChange = () => checkButtonDisabled()
  inputLogin.oninput = () => checkButtonDisabled()

  function checkButtonDisabled() {
    if (p.getValue() && inputLogin.value) inputButton.disabled = false
    else inputButton.disabled = true
  }

  this.getLogin = () => inputLogin.value
  this.setLogin = (value) => {
    inputLogin.value = value
    checkButtonDisabled()

  }
  this.getPass = () => p.getValue()
  this.setPass = (value) => {
    p.setValue(value)
    checkButtonDisabled()
  }

  inputButton.onclick = () => {
    if (typeof this.inputButtonOnclick === 'function') this.inputButtonOnclick() //функция при нажатии на кнопку войти
  }
  newUserAddButton.onclick = () => {
    if (typeof this.newUserAddButtonOnclick === 'function') this.newUserAddButtonOnclick()
  }
}
// let LoginFormInHeader = new LoginFormFunc(user)
// LoginFormInHeader.inputButtonOnclick = function () {
//   store.dispatch(actionFullLogin(this.getLogin(), this.getPass()))
// }
//vasya321986320915sf5654755ssddgfg пороль


store.subscribe(() => {
  let result = store.getState().auth?.payload?.sub?.login
  if (result) {
    user.innerHTML = result
    const buttonExitLogin = document.createElement('button')
    buttonExitLogin.innerHTML = 'выйти'
    buttonExitLogin.classList.add('buttonExitLogin')
    buttonExitLogin.onclick = () => {
      store.dispatch(actionAuthLogout())
      }
    user.append(buttonExitLogin)
    localStorage.authToken = store.getState().auth.token
    const buttonOrders = document.createElement('button')
    buttonOrders.innerHTML = 'история заказов'
    buttonOrders.classList.add('buttonOrders')
    buttonOrders.onclick = () => location.hash = '#/orders'
    user.append(buttonOrders)
  } else {
    delete localStorage.authToken
    user.innerHTML = "Unknown User"
    let LoginFormInHeader = new LoginFormFunc(user)
    LoginFormInHeader.inputButtonOnclick = () => {
      store.dispatch(actionFullLogin(this.getLogin(), this.getPass()))
    }
    LoginFormInHeader.newUserAddButtonOnclick = function () {
      store.dispatch(actionFullRegistration(this.getLogin(), this.getPass())) 
    }
  }
})

// store.subscribe(() => {
//   let arrResult = store.getState().promise.OrderFind?.payload
//   const [, route, _id] = location.hash.split('/')
//   if (arrResult && route === "orders") {
//     main.innerHTML = ""
//     let h1 = document.createElement('h1')
//     h1.innerText = "История заказов"
//     main.append(h1)
//     let orderTable = document.createElement('table')
//     main.append(orderTable)
//     orderTable.classList.add('table_price')
//     let firstTr = document.createElement('tr')
//     orderTable.append(firstTr)
//     firstTr.innerHTML = `<th></th><th>Номер заказа</th><th>Дата</th><th>Сумма, грн</th>`

//     let counter = 1
//     let summ = 0
//     for (let { _id, createdAt, total } of arrResult) {
//       let createdAtFormat = new Date(+createdAt)
//       let year = createdAtFormat.getFullYear()
//       let month = createdAtFormat.getMonth() < 9 ? "0" + (createdAtFormat.getMonth() + 1) : createdAtFormat.getMonth() + 1
//       let day = createdAtFormat.getDate() < 9 ? "0" + (createdAtFormat.getDate() + 1) : createdAtFormat.getDate() + 1
//       let hours = createdAtFormat.getHours() < 10 ? "0" + (createdAtFormat.getHours()) : createdAtFormat.getHours()
//       let minutes = createdAtFormat.getMinutes() < 10 ? "0" + (createdAtFormat.getMinutes()) : createdAtFormat.getMinutes()
//       const createdAtForTable = `${year}.${month}.${day} ${hours}:${minutes} `
//       orderTable.innerHTML += `<tr>
//         <td>${counter}</td>
//         <td>${_id}</td>
//         <td>${createdAtForTable}</td>
//         <td>${total}</td>
//         </tr>`
//       counter += 1
//       summ += total
//     }
//     orderTable.innerHTML += `<tr><td colspan="3"></td><td class="tdSumm">${summ} грн</td></tr>`
//   }
// })
function ordersToHTML (payload) {
  main.innerHTML = ""
    let h1 = document.createElement('h1')
    h1.innerText = "История заказов"
    main.append(h1)
    let orderTable = document.createElement('table')
    main.append(orderTable)
    orderTable.classList.add('table_price')
    let orderTableBody = document.createElement('tbody')
    orderTable.append(orderTableBody)

    let firstTr = document.createElement('tr')
    orderTableBody.append(firstTr)
    firstTr.innerHTML = `<th></th><th>Номер заказа</th><th>Дата</th><th>Сумма, грн</th>`

    let counter = 1
    let summ = 0
    let arrRevers = [...payload]
    for (let { _id, createdAt, total } of arrRevers.reverse()) {
      let createdAtFormat = new Date(+createdAt)
      let year = createdAtFormat.getFullYear()
      let month = createdAtFormat.getMonth() < 9 ? "0" + (createdAtFormat.getMonth() + 1) : createdAtFormat.getMonth() + 1
      let day = createdAtFormat.getDate() < 10 ? "0" + (createdAtFormat.getDate()) : createdAtFormat.getDate()
      let hours = createdAtFormat.getHours() < 10 ? "0" + (createdAtFormat.getHours()) : createdAtFormat.getHours()
      let minutes = createdAtFormat.getMinutes() < 10 ? "0" + (createdAtFormat.getMinutes()) : createdAtFormat.getMinutes()
      const createdAtForTable = `${year}.${month}.${day} ${hours}:${minutes} `
      orderTableBody.innerHTML += `<tr>
        <td>${counter}</td>
        <td>${_id}</td>
        <td>${createdAtForTable}</td>
        <td>${total}</td>
        </tr>`
      counter += 1
      summ += total
    }
    orderTableBody.innerHTML += `<tr><td colspan="3"></td><td class="tdSumm">${summ} грн</td></tr>`
}

store.subscribe(() => {

  const [, route, _id] = location.hash.split('/')
  if (route !== "orders") return
  const {status, payload, error} = store.getState().promise.OrderFind
  if (status === 'PENDING') {
    main.innerHTML = `<img src='giphy.gif'/>`
  }
  if (status === 'FULFILLED' && payload) {
    ordersToHTML (payload)
  }

  if (status === 'REJECTED') {
    main.innerHTML = `Что-то пошло не так, но мы скоро всё починим ;( \n сообщить о проблеме: <a href="mailto:mail@example.com">blablatest123@gmail.com</a>`
  }
})