import { createAsyncAction, errorResult, successResult } from "pullstate";

import { PostStore } from "stores";
import { updateWindowPosts } from "utils";

export const like = createAsyncAction(
  /**
   * @param {CF2021.Post} post
   */
  async (post) => {
    return successResult(post);
  },
  {
    shortCircuitHook: ({ args }) => {
      if (args.ranking.myVote !== "none") {
        return errorResult();
      }

      return false;
    },
    postActionHook: ({ result }) => {
      if (!result.error) {
        PostStore.update((state) => {
          state.items[result.payload.id].ranking.likes += 1;
          state.items[result.payload.id].ranking.score += 1;
          state.items[result.payload.id].ranking.myVote = "like";

          if (state.filters.sort === "byScore") {
            updateWindowPosts(state);
          }
        });
      }
    },
  }
);

export const removeLike = createAsyncAction(
  /**
   * @param {CF2021.Post} post
   */
  async (post) => {
    return successResult(post);
  },
  {
    shortCircuitHook: ({ args }) => {
      if (args.ranking.myVote !== "like") {
        return errorResult();
      }

      return false;
    },
    postActionHook: ({ result }) => {
      if (!result.error) {
        PostStore.update((state) => {
          state.items[result.payload.id].ranking.likes -= 1;
          state.items[result.payload.id].ranking.score -= 1;
          state.items[result.payload.id].ranking.myVote = "none";

          if (state.filters.sort === "byScore") {
            updateWindowPosts(state);
          }
        });
      }
    },
  }
);

export const dislike = createAsyncAction(
  /**
   * @param {CF2021.Post} post
   */
  async (post) => {
    return successResult(post);
  },
  {
    shortCircuitHook: ({ args }) => {
      if (args.ranking.myVote !== "none") {
        return errorResult();
      }

      return false;
    },
    postActionHook: ({ result }) => {
      if (!result.error) {
        PostStore.update((state) => {
          state.items[result.payload.id].ranking.dislikes += 1;
          state.items[result.payload.id].ranking.score -= 1;
          state.items[result.payload.id].ranking.myVote = "dislike";

          if (state.filters.sort === "byScore") {
            updateWindowPosts(state);
          }
        });
      }
    },
  }
);

export const removeDislike = createAsyncAction(
  /**
   * @param {CF2021.Post} post
   */
  async (post) => {
    return successResult(post);
  },
  {
    shortCircuitHook: ({ args }) => {
      if (args.ranking.myVote !== "dislike") {
        return errorResult();
      }

      return false;
    },
    postActionHook: ({ result }) => {
      if (!result.error) {
        PostStore.update((state) => {
          state.items[result.payload.id].ranking.dislikes -= 1;
          state.items[result.payload.id].ranking.score += 1;
          state.items[result.payload.id].ranking.myVote = "none";

          if (state.filters.sort === "byScore") {
            updateWindowPosts(state);
          }
        });
      }
    },
  }
);

/**
 * Add new discussion post.
 */
export const addPost = createAsyncAction(
  async ({ content }) => {
    /** @type {CF2021.DiscussionPost} */
    const payload = {
      id: "999",
      datetime: new Date(),
      author: {
        name: "John Doe",
        group: "KS Pardubický kraj",
      },
      type: "post",
      content,
      ranking: {
        score: 0,
        likes: 0,
        dislikes: 0,
        myVote: "none",
      },
      historyLog: [],
      archived: false,
      hidden: false,
      seen: true,
    };
    return successResult(payload);
  },
  {
    postActionHook: ({ result }) => {
      PostStore.update((state) => {
        state.items[result.payload.id] = result.payload;
        updateWindowPosts(state);
      });
    },
  }
);

/**
 * Add new proposal.
 */
export const addProposal = createAsyncAction(
  async ({ content }) => {
    /** @type {CF2021.ProposalPost} */
    const payload = {
      id: "999",
      datetime: new Date(),
      author: {
        name: "John Doe",
        group: "KS Pardubický kraj",
      },
      type: "procedure-proposal",
      state: "pending",
      content,
      ranking: {
        score: 0,
        likes: 0,
        dislikes: 0,
        myVote: "none",
      },
      historyLog: [],
      archived: false,
      hidden: false,
      seen: true,
    };

    return successResult(payload);
  },
  {
    postActionHook: ({ result }) => {
      PostStore.update((state) => {
        state.items[result.payload.id] = result.payload;
        updateWindowPosts(state);
      });
    },
  }
);