<template>
  <div class="normal-page__content">
    <div class="universal-card">
      <div class="label">
        <h3>
          <span class="label__title size-card-header">Manage members</span>
        </h3>
      </div>
      <span class="label">
        <span class="label__title">Invite a member</span>
        <span class="label__description">
          Enter the Modrinth username of the person you'd like to invite to be a member of this
          organization.
        </span>
      </span>
      <div class="input-group">
        <input
          id="username"
          v-model="currentUsername"
          type="text"
          placeholder="Username"
          :disabled="
            !isPermission(
              currentMember.organization_permissions,
              organizationPermissions.MANAGE_INVITES,
            )
          "
          @keypress.enter="() => onInviteTeamMember(organization.team, currentUsername)"
        />
        <label for="username" class="hidden">Username</label>
        <Button
          color="primary"
          :disabled="
            !isPermission(
              currentMember.organization_permissions,
              organizationPermissions.MANAGE_INVITES,
            )
          "
          @click="() => onInviteTeamMember(organization.team_id, currentUsername)"
        >
          <UserPlusIcon />
          Invite
        </Button>
      </div>
      <div class="adjacent-input">
        <span class="label">
          <span class="label__title">Leave organization</span>
          <span class="label__description">
            Remove yourself as a member of this organization.
          </span>
        </span>
        <Button
          color="danger"
          :disabled="currentMember.is_owner"
          @click="() => onLeaveProject(organization.team_id, auth.user.id)"
        >
          <UserRemoveIcon />
          Leave organization
        </Button>
      </div>
    </div>
    <div
      v-for="(member, index) in allTeamMembers"
      :key="member.user.id"
      class="member universal-card"
      :class="{ open: openTeamMembers.includes(member.user.id) }"
    >
      <div class="member-header">
        <div class="info">
          <Avatar :src="member.user.avatar_url" :alt="member.user.username" size="sm" circle />
          <div class="text">
            <nuxt-link :to="'/user/' + member.user.username" class="name">
              <p>{{ member.user.username }}</p>
              <CrownIcon v-if="member.is_owner" v-tooltip="'Organization owner'" />
            </nuxt-link>
            <p>{{ member.role }}</p>
          </div>
        </div>
        <div class="side-buttons">
          <Badge v-if="member.accepted" type="accepted" />
          <Badge v-else type="pending" />
          <Button
            icon-only
            transparent
            class="dropdown-icon"
            @click="
              openTeamMembers.indexOf(member.user.id) === -1
                ? openTeamMembers.push(member.user.id)
                : (openTeamMembers = openTeamMembers.filter((it) => it !== member.user.id))
            "
          >
            <DropdownIcon />
          </Button>
        </div>
      </div>
      <div class="content">
        <div class="adjacent-input">
          <label :for="`member-${member.user.id}-role`">
            <span class="label__title">Role</span>
            <span class="label__description">
              The title of the role that this member plays for this organization.
            </span>
          </label>
          <input
            :id="`member-${member.user.id}-role`"
            v-model="member.role"
            type="text"
            :disabled="
              !isPermission(
                currentMember.organization_permissions,
                organizationPermissions.EDIT_MEMBER,
              )
            "
          />
        </div>
        <div class="adjacent-input">
          <label :for="`member-${member.user.id}-monetization-weight`">
            <span class="label__title">Monetization weight</span>
            <span class="label__description">
              Relative to all other members' monetization weights, this determines what portion of
              the organization projects' revenue goes to this member.
            </span>
          </label>
          <input
            :id="`member-${member.user.id}-monetization-weight`"
            v-model="member.payouts_split"
            type="number"
            :disabled="
              !isPermission(
                currentMember.organization_permissions,
                organizationPermissions.EDIT_MEMBER,
              )
            "
          />
        </div>
        <template v-if="!member.is_owner">
          <span class="label">
            <span class="label__title">Project permissions</span>
          </span>
          <div class="permissions">
            <Checkbox
              v-for="[label, permission] in Object.entries(projectPermissions)"
              :key="permission"
              :model-value="isPermission(member.permissions, permission)"
              :disabled="
                !isPermission(
                  currentMember.organization_permissions,
                  organizationPermissions.EDIT_MEMBER_DEFAULT_PERMISSIONS,
                ) || !isPermission(currentMember.permissions, permission)
              "
              :label="permToLabel(label)"
              @update:model-value="allTeamMembers[index].permissions ^= permission"
            />
          </div>
        </template>
        <template v-if="!member.is_owner">
          <span class="label">
            <span class="label__title">Organization permissions</span>
          </span>
          <div class="permissions">
            <Checkbox
              v-for="[label, permission] in Object.entries(organizationPermissions)"
              :key="permission"
              :model-value="isPermission(member.organization_permissions, permission)"
              :disabled="
                !isPermission(
                  currentMember.organization_permissions,
                  organizationPermissions.EDIT_MEMBER,
                ) || !isPermission(currentMember.organization_permissions, permission)
              "
              :label="permToLabel(label)"
              @update:model-value="allTeamMembers[index].organization_permissions ^= permission"
            />
          </div>
        </template>
        <div class="input-group">
          <Button
            color="primary"
            :disabled="
              !isPermission(
                currentMember.organization_permissions,
                organizationPermissions.EDIT_MEMBER,
              )
            "
            @click="onUpdateTeamMember(organization.team_id, member)"
          >
            <SaveIcon />
            Save changes
          </Button>
          <Button
            v-if="!member.is_owner"
            color="danger"
            :disabled="
              !isPermission(
                currentMember.organization_permissions,
                organizationPermissions.EDIT_MEMBER,
              ) &&
              !isPermission(
                currentMember.organization_permissions,
                organizationPermissions.REMOVE_MEMBER,
              )
            "
            @click="onRemoveMember(organization.team_id, member)"
          >
            <UserRemoveIcon />
            Remove member
          </Button>
          <Button
            v-if="!member.is_owner && currentMember.is_owner && member.accepted"
            @click="() => onTransferOwnership(organization.team_id, member.user.id)"
          >
            <TransferIcon />
            Transfer ownership
          </Button>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import {
  SaveIcon,
  TransferIcon,
  UserPlusIcon,
  UserXIcon as UserRemoveIcon,
  DropdownIcon,
} from "@modrinth/assets";
import { Button, Badge, Avatar, Checkbox } from "@modrinth/ui";
import { ref } from "vue";
import CrownIcon from "~/assets/images/utils/crown.svg?component";

import { removeTeamMember } from "~/helpers/teams.js";
import { isPermission } from "~/utils/permissions.ts";

const { organization, refresh: refreshOrganization, currentMember } = inject("organizationContext");

const auth = await useAuth();

const currentUsername = ref("");
const openTeamMembers = ref([]);

const allTeamMembers = ref(organization.value.members);

watch(
  () => organization.value,
  () => {
    allTeamMembers.value = organization.value.members;
  },
);

const projectPermissions = {
  UPLOAD_VERSION: 1 << 0,
  DELETE_VERSION: 1 << 1,
  EDIT_DETAILS: 1 << 2,
  EDIT_BODY: 1 << 3,
  MANAGE_INVITES: 1 << 4,
  REMOVE_MEMBER: 1 << 5,
  EDIT_MEMBER: 1 << 6,
  DELETE_PROJECT: 1 << 7,
  VIEW_ANALYTICS: 1 << 8,
  VIEW_PAYOUTS: 1 << 9,
};

const organizationPermissions = {
  EDIT_DETAILS: 1 << 0,
  MANAGE_INVITES: 1 << 1,
  REMOVE_MEMBER: 1 << 2,
  EDIT_MEMBER: 1 << 3,
  ADD_PROJECT: 1 << 4,
  REMOVE_PROJECT: 1 << 5,
  DELETE_ORGANIZATION: 1 << 6,
  EDIT_MEMBER_DEFAULT_PERMISSIONS: 1 << 7,
};

const permToLabel = (key) => {
  const o = key.split("_").join(" ");
  return o.charAt(0).toUpperCase() + o.slice(1).toLowerCase();
};

const leaveProject = async (teamId, uid) => {
  await removeTeamMember(teamId, uid);
  await navigateTo(`/organization/${organization.value.id}`);
};

const onLeaveProject = useClientTry(leaveProject);

const onInviteTeamMember = useClientTry(async (teamId, username) => {
  const user = await useBaseFetch(`user/${username}`);
  const data = {
    user_id: user.id.trim(),
  };
  await useBaseFetch(`team/${teamId}/members`, {
    method: "POST",
    body: data,
  });
  await refreshOrganization();
  currentUsername.value = "";
  addNotification({
    group: "main",
    title: "Member invited",
    text: `${user.username} has been invited to the organization.`,
    type: "success",
  });
});

const onRemoveMember = useClientTry(async (teamId, member) => {
  await removeTeamMember(teamId, member.user.id);
  await refreshOrganization();
  addNotification({
    group: "main",
    title: "Member removed",
    text: `${member.user.username} has been removed from the organization.`,
    type: "success",
  });
});

const onUpdateTeamMember = useClientTry(async (teamId, member) => {
  const data = !member.is_owner
    ? {
        permissions: member.permissions,
        organization_permissions: member.organization_permissions,
        role: member.role,
        payouts_split: member.payouts_split,
      }
    : {
        payouts_split: member.payouts_split,
        role: member.role,
      };
  await useBaseFetch(`team/${teamId}/members/${member.user.id}`, {
    method: "PATCH",
    body: data,
  });
  await refreshOrganization();
  addNotification({
    group: "main",
    title: "Member updated",
    text: `${member.user.username} has been updated.`,
    type: "success",
  });
});

const onTransferOwnership = useClientTry(async (teamId, uid) => {
  const data = {
    user_id: uid,
  };
  await useBaseFetch(`team/${teamId}/owner`, {
    method: "PATCH",
    body: data,
  });
  await refreshOrganization();
  addNotification({
    group: "main",
    title: "Ownership transferred",
    text: `The ownership of ${organization.value.name} has been successfully transferred.`,
    type: "success",
  });
});
</script>

<style lang="scss" scoped>
.member {
  .member-header {
    display: flex;
    justify-content: space-between;
    .info {
      display: flex;
      .text {
        margin: auto 0 auto 0.5rem;
        font-size: var(--font-size-sm);

        .name {
          font-weight: bold;

          display: flex;
          align-items: center;
          gap: 0.25rem;

          svg {
            color: var(--color-orange);
          }
        }

        p {
          margin: 0.2rem 0;
        }
      }
    }
    .side-buttons {
      display: flex;
      align-items: center;
      .dropdown-icon {
        margin-left: 1rem;
        svg {
          transition: 150ms ease transform;
        }
      }
    }
  }
  .content {
    display: none;
    flex-direction: column;
    padding-top: var(--gap-md);
    .main-info {
      margin-bottom: var(--gap-lg);
    }
    .permissions {
      margin-bottom: var(--gap-md);
      max-width: 45rem;
      display: grid;
      grid-template-columns: repeat(auto-fill, minmax(10rem, 1fr));
      grid-gap: 0.5rem;
    }
  }
  &.open {
    .member-header {
      .dropdown-icon svg {
        transform: rotate(180deg);
      }
    }
    .content {
      display: flex;
    }
  }
}
:deep(.checkbox-outer) {
  button.checkbox {
    border: none;
  }
}
</style>
