<template>
  <div id="project-members">
    <h1 class="ui header">
      Gérer les membres
    </h1>

    <h4>Ajouter un membre</h4>

    <div
      id="form-feature-edit"
      class="ui form"
      name="add-member"
    >
      <div class="two fields">
        <div class="field">
          <Dropdown
            :options="userOptions"
            :selected="newMember.user.name"
            :selection.sync="newMember.user"
            :search="true"
            :clearable="true"
          />
          <ul
            id="errorlist"
            class="errorlist"
          >
            <li
              v-for="error in newMember.errors"
              :key="error"
            >
              {{ error }}
            </li>
          </ul>
        </div>
        <div class="field">
          <Dropdown
            :options="levelOptions"
            :selected="newMember.role.name"
            :selection.sync="newMember.role"
          />
        </div>
      </div>
      <button
        type="button"
        class="ui green icon button"
        :disabled="!newMember.user.name"
        @click="addMember"
      >
        <i
          class="white add icon"
          aria-hidden="true"
        />
        <span class="padding-1">Ajouter</span>
      </button>
    </div>

    <h4>Modifier le rôle d'un membre</h4>
    <div
      id="form-members"
      class="ui form"
    >
      <table
        class="ui red table"
        aria-describedby="Table des membres du projet"
      >
        <thead>
          <tr>
            <th scope="col">
              Membre
              <i
                :class="{
                  down: isSortedAsc('member'),
                  up: isSortedDesc('member'),
                }"
                class="icon sort"
                aria-hidden="true"
                @click="changeSort('member')"
              />
            </th>
            <th scope="col">
              Niveau d'autorisation
              <i
                :class="{
                  down: isSortedAsc('role'),
                  up: isSortedDesc('role'),
                }"
                class="icon sort"
                aria-hidden="true"
                @click="changeSort('role')"
              />
            </th>
          </tr>
        </thead>
        <tbody>
          <tr
            v-for="member in projectMembers"
            :key="member.username"
          >
            <td>
              {{ member.user.last_name }} {{ member.user.first_name }}<br><em>{{ member.user.username }}</em>
            </td>
            <td>
              <div class="required field online">
                <Dropdown
                  :options="levelOptions"
                  :selected="member.userLevel.name"
                  :selection.sync="member.userLevel"
                  :search="true"
                />
                <button
                  type="button"
                  class="ui icon button button-hover-red"
                  data-tooltip="Retirer ce membre"
                  @click="removeMember(member)"
                >
                  <i
                    class="times icon"
                    aria-hidden="true"
                  />
                </button>
              </div>
            </td>
          </tr>
        </tbody>
      </table>

      <div class="ui divider" />

      <button
        type="button"
        class="ui teal icon button"
        @click="saveMembers"
      >
        <i
          class="white save icon"
          aria-hidden="true"
        />&nbsp;Enregistrer les changements
      </button>
    </div>
  </div>
</template>

<script>
import axios from '@/axios-client.js';

import { mapMutations, mapState } from 'vuex';

import Dropdown from '@/components/Dropdown.vue';

export default {
  name: 'ProjectMembers',

  components: {
    Dropdown,
  },

  data() {
    return {
      projectUsers: [],
      options: [
        { name: 'Utilisateur connecté', value: 'logged_user' },
        { name: 'Contributeur', value: 'contributor' },
        { name: 'Super Contributeur', value: 'super_contributor' },
        { name: 'Modérateur', value: 'moderator' },
        { name: 'Administrateur projet', value: 'admin' },
      ],
      newMember: {
        errors: [],
        user: {
          name: '',
          value: '',
        },
        role: {
          name: 'Contributeur',
          value: 'contributor',
        },
      },
      sort: {
        column: '',
        ascending: true,
      },
    };
  },

  computed: {
    ...mapState('projects', ['project']),

    userOptions: function () {
      return this.projectUsers
        .filter((el) => el.userLevel.value === 'logged_user')
        .map((el) => {
          let name = el.user.first_name || '';
          if (el.user.last_name) {
            name = name + ' ' + el.user.last_name;
          }
          return {
            name: [name, el.user.username],
            value: el.user.id,
          };
        });
    },

    levelOptions: function () {
      return this.options.filter(
        (el) =>
          (this.project && this.project.moderation ? el : el.value !== 'moderator') &&
          el.value !== 'logged_user'
      );
    },

    projectMembers() {
      return this.projectUsers
        .filter((el) => el.userLevel.value !== 'logged_user')
        .sort((a, b) => {
          if (this.sort.column !== '') {
            if (this.sort.column === 'member') {
              const textA = a.user.username.toUpperCase();
              const textB = b.user.username.toUpperCase();
              if (this.sort.ascending) {
                return textA < textB ? -1 : textA > textB ? 1 : 0;
              } else {
                return textA > textB ? -1 : textA < textB ? 1 : 0;
              }
            } else if (this.sort.column === 'role') {
              const textA = a.userLevel.name.toUpperCase();
              const textB = b.userLevel.name.toUpperCase();
              if (this.sort.ascending) {
                return textA < textB ? -1 : textA > textB ? 1 : 0;
              } else {
                return textA > textB ? -1 : textA < textB ? 1 : 0;
              }
            }
          } else {
            return 0;
          }
        });
    },
  },

  created() {
    if (!this.project) {
      this.$store.dispatch('projects/GET_PROJECT', this.$route.params.slug);
      this.$store.dispatch('projects/GET_PROJECT_INFO', this.$route.params.slug);
    }
    this.populateMembers();
  },

  destroyed() {
    //* allow user to change page if ever stuck on loader
    this.DISCARD_LOADER();
  },

  methods: {
    ...mapMutations([
      'DISPLAY_MESSAGE',
      'DISPLAY_LOADER',
      'DISCARD_LOADER'
    ]),

    validateNewMember() {
      this.newMember.errors = [];
      if (!this.newMember.user.value) {
        this.newMember.errors.push('Veuillez compléter ce champ.');
        return false;
      }
      return true;
    },

    changeUserRole(id, role) {
      const indexOfUser = this.projectUsers.findIndex(
        (el) => el.user.id === id
      );
      //* modify its userLever
      this.projectUsers[indexOfUser].userLevel = role;
    },

    addMember() {
      if (this.validateNewMember()) {
        this.changeUserRole(this.newMember.user.value, this.newMember.role);
        //* empty add form
        this.newMember.user = { value: '', name: '' };
      }
    },

    isSortedAsc(column) {
      return this.sort.column === column && this.sort.ascending;
    },
    isSortedDesc(column) {
      return this.sort.column === column && !this.sort.ascending;
    },

    changeSort(column) {
      if (this.sort.column === column) {
        //changer order
        this.sort.ascending = !this.sort.ascending;
      } else {
        this.sort.column = column;
        this.sort.ascending = true;
      }
    },

    removeMember(member) {
      this.changeUserRole(member.user.id, {
        name: 'Utilisateur connecté',
        value: 'logged_user',
      });
    },

    /**
     * Saves the updated members and their roles for a project.
     * Displays a loader while the update is in progress and provides feedback upon completion or error.
     */
    saveMembers() {
      // Display a loader to indicate that the update process is ongoing
      this.DISPLAY_LOADER('Updating project members...');

      // Prepare the data to be sent in the API request
      const data = this.projectUsers.map((member) => {
        return {
          user: member.user,
          level: {
            display: member.userLevel.name,  // Display name of the user level
            codename: member.userLevel.value, // Codename of the user level
          },
        };
      });

      // Make an API request to update the project members
      axios
        .put(
          `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.project.slug}/utilisateurs/`,
          data
        )
        .then((response) => {
          // Check if the response status is 200 (OK)
          if (response.status === 200) {
            // Dispatch an action to update the user status in the top right menu
            this.$store.dispatch('GET_USER_LEVEL_PROJECTS');
            // Display a positive message indicating success
            this.DISPLAY_MESSAGE({ comment: 'Permissions updated successfully', level: 'positive' });
          } else {
            // Display a generic error message if the response status is not 200
            this.DISPLAY_MESSAGE({
              comment: "An error occurred while updating permissions",
              level: 'negative'
            });
          }
          // Hide the loader regardless of the request result
          this.DISCARD_LOADER();
        })
        .catch((error) => {
          // Hide the loader if an error occurs
          this.DISCARD_LOADER();
          // Determine the error message to display
          const errorMessage = error.response && error.response.data && error.response.data.error
            ? error.response.data.error
            : "An error occurred while updating permissions";
          // Display the error message
          this.DISPLAY_MESSAGE({
            comment: errorMessage,
            level: 'negative'
          });
          // Log the error to the console for debugging
          console.error(error);
        });
    },

    fetchMembers() {
      // todo: move function to a service
      return axios
        .get(
          `${this.$store.state.configuration.VUE_APP_DJANGO_API_BASE}projects/${this.$route.params.slug}/utilisateurs/`
        )
        .then((response) => response.data)
        .catch((error) => {
          throw error;
        });
    },

    populateMembers() {
      this.DISPLAY_LOADER('Récupération des membres en cours...');
      this.fetchMembers().then((members) => {
        this.DISCARD_LOADER();
        this.projectUsers = members.map((el) => {
          return {
            userLevel: { name: el.level.display, value: el.level.codename },
            ...el,
          };
        });
      });
    },
  },
};
</script>

<style>
.padding-1 {
  padding: 0 1em;
}

i.icon.sort:not(.down):not(.up) {
  color: rgb(220, 220, 220);
}

.online {
  display: flex;
}
</style>