const getGQL = (url) => (query, variables) =>
  fetch(url, {
    method: "POST",
    headers: {
      "content-type": "application/json",
      ...(localStorage.authToken
        ? { Authorization: "Bearer " + localStorage.authToken }
        : {}),
    },
    body: JSON.stringify({ query, variables }),
  }).then((res) => res.json());

export const gql = getGQL("/graphql");

const reg = async (login, password) => {
  let query = `mutation reg($login: String!, $password: String!) {
    createUser(login: $login, password: $password)
		{
      _id
      login

    }
}`;
  let variables = {
    login: login,
    password: password,
  };
  let result = await gql(query, variables);
  return result;
};

const log = async (login, password) => {
  let query = `query login($login:String!, $password:String!) {
      login(login: $login, password: $password)
    }`;
  let variables = {
    login: login,
    password: password,
  };
  let result = await gql(query, variables);
  console.log(result);
  return result;
};

export const upload = async (file) => {
  let fd = new FormData();
  fd.append("photo", file);
  return fetch("/upload", {
    method: "POST",
    headers: localStorage.authToken
      ? { Authorization: "Bearer " + localStorage.authToken }
      : {},
    body: fd,
  }).then((res) => res.json());
};

export const actionPromise = (name, promise) => async (dispatch) => {
  dispatch(actionPending(name));
  try {
    let payload = await promise;
    dispatch(actionResolved(name, payload));
    return payload;
  } catch (error) {
    dispatch(actionRejected(name, error));
  }
};

export const actionShowFollowers = (id) => {
  return actionPromise(
    "getFollowers",
    gql(
      `query getFollowers($_id: String) {
        UserFindOne(query: $_id) {
          followers{
           _id
           login
           avatar {
               url
           },
          }
        }
      }`,
      {
        _id: JSON.stringify([{ _id: id }])
      }
    )
  )
}
export const actionShowFollowing = (id) => {
  return actionPromise(
    "getFollowing",
    gql(
      `query getFollowing($_id: String) {
         UserFindOne(query: $_id) {
           following{
            _id
            login
            avatar {
                url
            },
           }
         }
       }`,
      {
        _id: JSON.stringify([{ _id: id }])
      }
    )
  )
}


export const getOnePost = (_id) =>
  actionPromise(
    "getOnePost",
    gql(
      `query OneFind($post:String){
       PostFindOne(query:$post){
        _id title text images{_id url}
        owner{_id login avatar{_id url}}
        createdAt
        comments{
          _id, createdAt, text  owner{_id login avatar{_id url}}
          answers{
            _id, createdAt, text owner{_id login  avatar{_id url}}
            
          }
        owner{_id login avatar{_id url}}}
        likes{
          _id
          owner{				
              _id login avatar {_id url}
            }
        }
      }
    }`,
      {
        post: JSON.stringify([{ _id }]),
      }
    )
  );


export const actionUserById = (id) => {
  return actionPromise(
    "UserById",
    gql(
      `query UserById($_id:String) {
        UserFindOne(query: $_id){
          _id, nick, login, avatar {url}
          followers {_id, nick, login, avatar {url}},
          following {_id, nick, login,avatar {url}}
          } 
        }`,
      { _id: JSON.stringify([{ _id: id }]) }
    )
  );
};

export const actionGetPosts = (skip) => {
  // console.log('news')
  return actionPromise(
    "allPosts",
    gql(
      `query allposts($query: String!){
          PostFind(query: $query){
            _id, text, title,
            owner{_id, nick, login, avatar 
              {
                url
              }
            }, 
            images{url},
            comments{
              answerTo{
                text
                owner{
                  login
                  avatar{
                    url
                  }
                }
              }
                          answers{
                text
                owner{
                  login
                  avatar{
                    url
                  }
                }
              }
              likesCount

              likes{
                _id
                owner{
                  _id
                  login
                  avatar{
                    url
                  }
                }
              }
              _id
              text,
              likesCount
              owner {
                _id
                login,
                avatar {
                  url
                }
                
              }
            },
            likes {
              _id
              owner {
                _id
                nick
                login
              }
            }
            createdAt
        }
      }`,
      {
        query: JSON.stringify([
          {},
          { sort: [{ _id: -1 }], skip: [skip || 0], limit: [500] },
        ]),
      }
    )
  );
};




export const actionGetUsers = (skip) => {
  console.log("users");
  return actionPromise(
    "allUsers",
    gql(
      `query allUsers($query: String!){
    UserFind(query: $query){
      _id, login, nick, avatar 
       {_id, url}
     }
  }`,
      {
        query: JSON.stringify([
          {},
          { sort: [{ login: -1 }], skip: [skip || 0], limit: [500000] },
        ]),
      }
    )
  );
};

export const actionInsertPosts = (title, text, _id) => {
  console.log("post");
  return actionPromise(
    "InsertPosts",
    gql(
      `mutation newPost($post:PostInput){
    PostUpsert(post:$post){
      _id 
    }
  }`,
      { post: { title: title, text: text, images: { _id: _id } } }
    )
  );
};

export const actionSendComment = (postId, text) =>
  actionPromise(
    gql(
      `mutation AddComment($comment:CommentInput){
          CommentUpsert(comment:$comment)
          {
            _id
            text
            createdAt
            likesCount
            likes {
              _id
            }
          }
        }`,
      {
        comment: {
          post: {
            _id: postId,
          },
          text,

        },
      }
    )
  );

export const actionAnswerComment = (commentId, text) =>
  actionPromise(
    gql(
      `mutation AddCommentAnswe($comment:CommentInput){
          CommentUpsert(comment:$comment)
          {
            _id
            text 
            owner{
              avatar{
                url
              }
            }
           
          }
        }`,
      {
        comment: {
          _id: commentId,

          answerTo: {
            text: text,

          },

        },
      }
    )
  );




const actionPending = (name) => ({ type: "PROMISE", status: "PENDING", name });
const actionResolved = (name, payload) => ({
  type: "PROMISE",
  status: "RESOLVED",
  name,
  payload,
});
const actionRejected = (name, error) => ({
  type: "PROMISE",
  status: "REJECTED",
  name,
  error,
});
const actionAuthLogin = (token) => ({ type: "LOGIN", token });
export const actionAuthLogout = () => ({ type: "LOGOUT" });
export const actionLogin = (login, password) =>
  actionPromise("login", log(login, password));
const actionRegister = (login, password) =>
  actionPromise("register", reg(login, password));
export const actionFullLogin = (login, password) => async (dispatch) => {
  let token = await dispatch(actionLogin(login, password));
  console.log(token);
  if (token?.data?.login) {
    console.log(token.data.login);
    dispatch(actionAuthLogin(token.data.login));
  } else {
    console.log("Authorization failed");
    // dispatch(actionLoginNetworkError())
  }
};
export const actionFullRegister = (login, password) => async (dispatch) => {
  let token = await dispatch(actionRegister(login, password));
  console.log(token);
  if (token?.data?.createUser !== null) {
    dispatch(actionFullLogin(login, password));
  } else {
    alert("User name is exist");
  }
};
export const actionUploadFile = (file) => actionPromise("upload", upload(file));

export const actionUploadPost = (text, title, file) => async (dispatch) => {
  let result = await dispatch(actionUploadFile(file));
  let postId = await dispatch(actionInsertPosts(text, title, result._id));
  dispatch(actionGetPosts());
  console.log(postId);
};

export const actionInsertPhoto = (userId, photoId) => {
  console.log("post");
  return actionPromise(
    "InsertPosts",
    gql(
      `mutation setUserAvatar($avatar: ImageInput){
    ImageUpsert(image: $avatar){
        _id, userAvatar {_id}
    }
  }`,
      { avatar: { _id: userId, userAvatar: { _id: photoId } } }
    )
  );
};

export const actionUploadPhoto = (file, userId) => async (dispatch) => {
  let result = await dispatch(actionUploadFile(file));
  console.log(userId, result._id);
  dispatch(actionInsertPhoto(result._id, userId));
};

export const actionPostById = (id) => {
  return actionPromise(
    "PostById",
    gql(
      `query PostById($_id:String) {
      PostFind(query: $_id){
        _id createdAt title text,
        images {url},
        likes{
          _id
        }
        comments{
          text
          owner{
            avatar{
              url
            }
          }
          answerTo{
            text
            owner{
              avatar{
                url
              }
            }
          }
        }
        owner {login, nick, avatar {url},
        followers {_id, nick, login},
    		following {_id, nick, login}}
      }
	} `,
      { _id: JSON.stringify([{ ___owner: id }]) }
    )
  );
};

export const actionSubscribe = (id, token) => {
  console.log("subscribe");
  return actionPromise(
    "Subscribe",
    gql(
      `mutation following($user:UserInput){
        UserUpsert( user:$user){
            following {
              _id
              nick
            }
        }
      }`,
      {
        user: {
          _id: id,
          following: [{ _id: token }],
        },
      }
    )
  );
};



export const delete_post = (id) => {
  console.log("subscribe");
  return (
    "delete post ",
    gql(
      `mutation deletePost($_id:PostInput){
        PostDelete( post:$_id){
          _id
        }
      }`,
      {
        _id: {
          _id: id,

        },
      }
    )
  );
};


export const updateProfileNickname = (userId, nickname) =>
  actionPromise(
    gql(
      `mutation updateUserProfile($user:UserInput){
        UserUpsert(user:$user){
          login
        }
      }`,
      {
        user: {
          _id: userId,
          login: nickname

        }
      }
    )
  )