import { store } from "."
import { useGetState } from 'react-redux';

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 = nameOfPromise => ({ nameOfPromise, type: 'PROMISE', status: 'PENDING' })
export const actionFulfilled = (nameOfPromise, payload) => ({ nameOfPromise, type: 'PROMISE', status: 'FULFILLED', payload })
export const actionRejected = (nameOfPromise, error) => ({ nameOfPromise, type: 'PROMISE', status: 'REJECTED', error })

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





// =============================================================
// Запросы на бек

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

)

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


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


//  запрос на изменение пароля юзера
export const actionPassChange = (loginChange, passwordChange, passwordNew) => actionPromise('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('PostFindOne', gql(`query OnePostFind ($postOne: String){
  PostFindOne (query: $postOne) {
    _id createdAt title text likesCount
    images {
      url
    }
    comments {
      _id createdAt text answers {
        _id createdAt text likes {
          _id
        }
        likesCount owner {
          _id login nick  avatar {
            _id url
          }
        }
      }
      likesCount
    }
    owner {
      _id login nick avatar {
        _id url
      }
    }
    
  }
}`, {
  postOne: JSON.stringify([{ _id }])
}))

// запрос на поиск конкретного юзера(folowwing - это те, на кого я подписан. followers - те, кто на меня подписан)
// export const actionFindUserOne = (_id, promiseName = 'UserFindOne') => actionPromise(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(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
      }
    }
  }`, {
  userOne: JSON.stringify([{ _id }])
}))

// запрос на поиск всех постов на беке (нигде не должен использоваться)
export const actionfindPosts = () => actionPromise('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, promiseName = 'Feed') => actionPromise(promiseName, gql(`query FeedFindOne ($feedOne: String){
	PostFind(query: $feedOne){
            _id createdAt title text likesCount owner{
              _id login avatar{
                url
              }
            }
            comments {
              _id
            }
    images{
      url
    }
    	}
    }`, {
  feedOne: JSON.stringify([{ ___owner: { $in: arr } }, { sort: [{ _id: sortOne }] }])
}))




// =========================================
// 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 => {
    // чистим полностью localStorage
    await dispatch(actionAuthLogout())

    // и перебрасываем пользователя на страницу авторизации
    // window.location.replace('/authorization')


    setTimeout(function () {
      window.location.replace('/')
    }, 500)

  }


// Thunk для страницы юзера (диспатчим запрос на юзера и на ленту его постов)
export const actionFullUserFindOne = (id) =>
  async dispatch => {
    const test = await dispatch(actionFindUserOne(id, 'UserFind'))
    console.log('test: ', test)
    dispatch(actionFeedFindOne([id], -1, 'UserFeed'))
  }


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

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

    // парсим все мои посты
    dispatch(actionFeedFindOne([myId], -1, 'MyPosts'))

    // получаем id всех подписок
    const followingList = (userData?.following).map(user => user?._id)

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

  }




// запрос на загрузку картинок на бек
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('FilesUpload',
  filesUpload(files)
)



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

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

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





