const url = 'http://hipstagram.node.ed.asmer.org.ua/graphql'


// функция getGql
function getGql(endpoint) {
  return async function gql(query, variables = {}) {

    let headers = {
      'Content-Type': 'application/json;charset=utf-8',
      'Accept': 'application/json',
    }
    if (('authToken' in localStorage)) {
      headers.Authorization = 'Bearer ' + localStorage.authToken
    }

    let result = await fetch(endpoint, {
      method: 'POST',
      headers,
      body: JSON.stringify({
        query,
        variables
      })
    }).then(res => res.json())

    if (('errors' in result) && !('data' in result)) {
      throw new Error(JSON.stringify(result.errors))
    }

    result = Object.values(result.data)[0]

    return result
  }
}

const gql = getGql(url)

// акшоны для promiseReducer
export const actionPending = (type, nameOfPromise) => ({ nameOfPromise, type, status: 'PENDING' })
export const actionFulfilled = (type, nameOfPromise, payload) => ({ nameOfPromise, type: type, status: 'FULFILLED', payload })
export const actionRejected = (type, nameOfPromise, error) => ({ nameOfPromise, type: type, status: 'REJECTED', error })

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




// акшон для логинизации в authReduser
export const actionAuthLogin = token => ({ type: 'AUTH_LOGIN', token })

// акшон для раззлогинивания в authReduser
export const actionAuthLogout = () => ({ type: 'AUTH_LOGOUT' })



// Запрос на регистрацию юзера
export const actionRegistration = (login, password) => actionPromise('PROMISE', 'Registration', gql(`mutation Registration($login:String!, $password:String!) {
   createUser(login:$login, password:$password) {
    _id login
  }
}`, {
  login,
  password
}))



// Запрос на логинизацию юзера
export const actionLogin = (login, password) => actionPromise('PROMISE', 'Login', gql(`query Login($login: String!, $password: String!) {
login(login: $login, password: $password)
}`, {
  login,
  password
}))



// Запрос на изменение пароля юзера
export const actionPassChange = (loginChange, passwordChange, passwordNew) => actionPromise('PROMISE', 'PassChange', gql(`mutation PasswordChange($loginChange: String!, $passwordChange: String!, $passwordNew: String!) {
  changePassword(
    login: $loginChange, password: $passwordChange, newPassword: $passwordNew
  ) {
       _id login

  }
}`, {
  loginChange,
  passwordChange,
  passwordNew
}))



// Запрос на поиск конкретного поста
export const actionFindPostOne = _id => actionPromise('PROMISE', 'PostFindOne', gql(`query OnePostFind ($postOne: String){
  PostFindOne (query: $postOne) {
    _id createdAt title text likesCount
    images {
      url
    }
    comments {
      _id createdAt text likesCount
      owner {
        _id login
        avatar {
          url
        }
      }
      answers {
        _id createdAt text likes {
          _id
        }
        likesCount owner {
          _id login nick  avatar {
            _id url
          }
        }
      }
    }
    owner {
      _id login nick avatar {
        _id url
      }
    }
    likes {
      _id owner{
        _id login avatar {
          _id url
        }
      }
    }
  }
}`, {
  postOne: JSON.stringify([{ _id }])
}))



// запрос на поиск конкретного юзера(folowwing - это те, на кого я подписан. followers - те, кто на меня подписан)
// export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise('PROMISE', promiseName, gql(`query OneUserFind ($userOne: String) {
//     UserFindOne(query: $userOne) {
//       _id createdAt login nick
//       avatar {
//         _id url
//       }
//        followers {
//         _id login nick avatar {_id url}
//       }
//       following {
//          _id login nick avatar {_id url}
//       }
//     }
//   }`, {
//   userOne: JSON.stringify([{ _id }])
// }))
export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise('PROMISE', promiseName, gql(`query OneUserFind ($userOne: String) {
    UserFindOne(query: $userOne) {
      _id createdAt login nick 
      avatar {
        _id url
      } 
       followers {
        _id login avatar {_id url}
      }
      following {
         _id login avatar {_id url}
      }
    }
  }`, {
  userOne: JSON.stringify([{ _id }])
}))



// Запрос на поиск всех постов на беке (нигде не должен использоваться)
export const actionfindPosts = () => actionPromise('PROMISE', 'PostsFind', gql(`query AllPostsFind ($allPosts: String){
  PostFind(query: $allPosts){
    _id createdAt title text likesCount
    images {
      url
    }
    owner {
      _id login nick
    }
    
  }
}`, {
  allPosts: JSON.stringify([{}])
}))



// Запрос на поиск ленты постов для юзера
// export const actionFeedFindOne = (arr, sortOne, limitOne, promiseName = 'Feed') => actionPromise('PROMISE', promiseName, gql(`query FeedFindOne ($feedOne: String){
// 	PostFind(query: $feedOne){
//             _id createdAt title text likesCount owner{
//               _id login avatar{
//                 url
//               }
//             }
//             comments {
//               _id
//             }
//     images{
//       url
//     }
//     	}
//     }`, {
//   // вот тут прописал limit - количество постов, которые отображаются в ленте
//   feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], limit: [limitOne] }])
// }))

//================= вот это тоже нужно будет удалить после тестов =====================
export const actionFeedFindOne = (arr, sortOne, limitOne, promiseName = 'Feed', skipOne = 0) => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){
	PostFind(query: $feedOne){
            _id createdAt title text owner{
              _id login avatar{
                url
              }
            }
            comments {
              _id
            }
    images{
      url
    }
    likes{
      _id owner{
        _id login
      }
    }
    	}
    }`, {
  // вот тут прописал limit - количество постов, которые отображаются в ленте
  feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], limit: [limitOne], skip: [skipOne] }])
}))



// Запрос ленты с пропуском определенного количества постов/комментов
// export const actionFeedFindOneSkip = (arr, sortOne, skipOne, limitOne, promiseName = 'Feed') => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){
// 	PostFind(query: $feedOne){
//             _id createdAt title text likesCount owner{
//               _id login avatar{
//                 url
//               }
//             }
//             comments {
//               _id
//             }
//     images{
//       url
//     }
//     	}
//     }`, {
//   // вот тут прописал limit - количество постов, которые отображаются в ленте
//   feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], skip: [skipOne], limit: [limitOne] }])
// }))

// ====================== и это удалить после теста ====================
export const actionFeedFindOneSkip = (arr, sortOne, skipOne, limitOne, promiseName = 'Feed') => actionPromise('FEED', promiseName, gql(`query FeedFindOne ($feedOne: String){
	PostFind(query: $feedOne){
            _id createdAt title text likesCount owner{
              _id login avatar{
                url
              }
            }
            comments {
              _id
            }
    images{
      url
    }
    likes{
      _id owner{
        _id login
      }
    }
    	}
    }`, {
  // вот тут прописал limit - количество постов, которые отображаются в ленте
  feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }], skip: [skipOne], limit: [limitOne] }])
}))



// Запрос на подсчет количества постов юзера
export const actionPostsCount = (id, promiseName) => actionPromise('PROMISE', promiseName, gql(`query PostsCount ($postsCount: String){
  PostCount(query: $postsCount)
}`, {
  postsCount: JSON.stringify([{ ___owner: id }])
}))



// Запрос на создание поста
export const actionCreatePost = params => actionPromise('PROMISE', 'CreatePost', gql(`mutation CreatePost($createNewPost: PostInput){
  PostUpsert(post: $createNewPost){
    _id
  }
}`, {
  createNewPost: params
}))




// запрос на создание комментария с последующим добавлением его к посту
export const actionAddComment = (NameOfPromise, params) => actionPromise('PROMISE', NameOfPromise, gql(`mutation AddComment($createComment: CommentInput){
  CommentUpsert(comment: $createComment){
    _id createdAt text
  }
}`, {
  createComment: params
}))




// запрос на поиск всех ответов, которые есть у данного комментария
export const actionFindCommentsAnswerTo = id => actionPromise('PROMISE', 'FindCommentsAnswerTo', gql(`query FindCommentAnswers2($answerTo: String) {
  CommentFind(query: $answerTo){
  _id createdAt text likesCount
    answers{
      _id
    }
    owner{
      _id login avatar{
        url
      }
    }
  }
}`, {
  answerTo: JSON.stringify([{ 'answerTo._id': id }])
}))






// запрос на поиск всех комментариев, которые есть у поста
export const actionFindCommentsPostOne = id => actionPromise('PROMISE', 'FindComments', gql(`query FindCommentsToPost($commentsToPost: String) {
  CommentFind(query: $commentsToPost){
  _id createdAt text likesCount
    answerTo{
      _id
    }
    owner{
      _id login avatar{
        url
      }
    }
    likes {
      _id
    }
  }
}`, {
  commentsToPost: JSON.stringify([{ 'post._id': id }, { sort: [{ _id: -1 }] }])
}))




// поиск всех подписчиков конкретных юзеров(бек фильтрует все дубли)
export const actionFindFollowers = arr => actionPromise('PROMISE', 'FindFollowers', gql(`query FindFollowers($findFollowers: String){
  UserFind(query: $findFollowers){
      _id login
      avatar{
        _id url
    }
  }
}`, {
  findFollowers: JSON.stringify([{ 'followers._id': { $in: arr } }])
}))

// поиск всех подписок конкретных юзеров(бек фильтрует все дубли)
export const actionFindFollowing = arr => actionPromise('PROMISE', 'FindFollowings', gql(` query FindFollowing($findFollowing: String){
  UserFind(query: $findFollowing){
      _id login
      avatar{
        _id url
    }
  }
}`, {
  findFollowing: JSON.stringify([{ 'following._id': { $in: arr } }])
}))





// добавление  лайка к посту/комментарию
export const actionAddLike = params => actionPromise('PROMISE', 'AddLike', gql(`mutation addLike($addLike: LikeInput){
  LikeUpsert(like: $addLike){
    _id
    post{
      _id title likes{
        _id 
      }
    }
    comment{
      _id text likes{
        _id 
      }
    }
    owner{
      _id 
    }
  }
}`, {
  addLike: params
}))





// удаление лайка с поста/комментария (пример данных: {_id: "6421f0e9cec75c3ebd51bed5"})
export const actionDeleteLike = params => actionPromise('PROMISE', 'DeleteLike', gql(`mutation deleteLike($deleteLike: LikeInput){
  LikeDelete(like: $deleteLike){
    _id post{
      _id
    }
  }
}`, {
  deleteLike: params
}))






//обновление профил(установка аватара, ник-нейма, логина?, добавления/удаления подписчиков)
export const actionUpdateProfile = params => actionPromise('PROMISE', 'UpdateProfile', gql(`mutation setAvatar($updateProfile: UserInput){
    UserUpsert(user: $updateProfile){
        _id, avatar{
            _id
        }
    }
}`, {
  updateProfile: params
}))















// =========================================
// Thunk-и

// Thunk логин и последующую логинизацию в authReduser
// export const actionFullLogin = (login, password) =>
//   async dispatch => {

//     const token = await dispatch(actionLogin(login, password))

//     if (token !== null) {
//       if (typeof (token) === 'string') {
//         dispatch(actionAuthLogin(token))
//         localStorage.authToken = token
//       }
//     }

//     return token
//   }






// Thunk на регистрацию и последующую логинизацию
// export const actionFullRegistration = (login, password) =>
//   async dispatch => {

//     const token = await dispatch(actionRegistration(login, password))

//     if (token !== null) {
//       dispatch(actionFullLogin(login, password))
//     }

//     return token
//   }





// Thunk разлогина и последующей полной очистки localStorage
// export const actionFullLogout = () =>
//   async dispatch => {
//     await dispatch(actionAuthLogout())
//     return {}
//   }





// Thunk для страницы юзера (диспатчим запрос на юзера и на ленту его постов)
// export const actionFullUserFindOne = _id =>
//   async dispatch => {

//     // запрашиваем информацию о пользователе
//     await dispatch(actionFindUserOne(_id, 'UserFindOne'))

//     // парсим счетчик, сколько постов у юзера
//     dispatch(actionPostsCount(_id, 'UserPostsCount'))

//     // запрашиваем список постов для юзера
//     dispatch(actionFeedFindOne([_id], -1, 100, 'UserFeed'))
//   }






// запрос AboutMe для главной страницы (лента моих постов и мои данные)
// export const actionAboutMe = () =>
//   async (dispatch, getState) => {
//     const myId = getState()?.auth?.payload?.sub?.id

//     // диспатчим запрос AboutMe (о себе)
//     const userData = await dispatch(actionFindUserOne(myId, 'AboutMe'))

//     // парсим счетчик, сколько постов у меня
//     dispatch(actionPostsCount(myId, 'MyPostsCount'))

//     let followingList = []
//     // проверяем, есть ли вообще подписчики и если да, парсим их
//     if (userData?.following) {
//       // получаем id всех подписок
//       followingList = (userData.following).map(user => user?._id)
//     }

//     // запрашиваем формирование ленты моих постов (первый параметр - список id, второй - это сортировка постов от новых)
//     dispatch(actionFeedFindOne(followingList, -1, 10, 'MyFeed'))
//   }




// ================= на удаление (начало)=====================

// export const actionDownloadFeed = (skip) =>
//   async (dispatch, getState) => {

//     console.log('скипаем: ', skip)
//     const followingList = (getState()?.promise?.AboutMe?.payload?.following).map(user => user._id)

//     if (followingList) {
//       const result = await dispatch(actionFeedFindOne(followingList, -1, 10, 'AddFeed', skip))

//       return result
//     }
//   }


// ================= на удаление(конец) =====================



// запрос на загрузку картинок на бек
// function fileUpload(file) {
//   const formData = new FormData()
//   formData.append('photo', file)

//   return (
//     fetch('http://hipstagram.node.ed.asmer.org.ua/upload', {
//       method: 'POST',
//       headers: {
//         Authorization: 'Bearer ' + localStorage.authToken
//       },
//       body: formData
//     }).then(res => res.json())
//   )
// }

// function filesUpload(files) {
//   return Promise.all(files.map(fileUpload))
// }

// export const actionFilesUpload = (files) => actionPromise('PROMISE', 'FilesUpload',
//   filesUpload(files)
// )
















// санк для создания поста и последующего перехода на его страницу
// export const actionFullCreatePost = (params) =>
//   async dispatch => {
//     const newPost = await dispatch(actionCreatePost(params))
//     // console.log('Тут нужный резульата: ', newPost)

//     if (newPost) {
//       dispatch(actionFindPostOne(newPost._id))
//     }
//   }





