<template>
  <div class="space-y-4">
    <!-- Loading State -->
    <div v-if="isLoading" class="flex justify-center items-center py-8">
      <fa icon="spinner" class="fa-spin-pulse" />
    </div>

    <!-- Members List -->
    <div v-else class="space-y-4">
      <div v-if="missingMyself" class="py-4">
        You are not yet admitted. The organizer will admit you.
      </div>
      <div
        v-for="member in decryptedMembers"
        :key="member.member.memberId"
        class="p-4 bg-gray-50 rounded-lg"
      >
        <div class="flex items-center">
          <h3 class="text-lg font-medium">{{ member.name }}</h3>
          <button
            v-if="isOrganizer && member.did !== activeDid"
            @click="toggleAdmission(member.member)"
            class="ml-2 w-6 h-6 flex items-center justify-center rounded-full bg-blue-100 text-blue-600 hover:bg-blue-200 hover:text-blue-800 transition-colors"
            :title="member.member.admitted ? 'Remove member' : 'Admit member'"
          >
            <fa :icon="member.member.admitted ? 'minus' : 'plus'" class="text-sm" />
          </button>
        </div>
        <p class="text-sm text-gray-600">{{ member.did }}</p>
      </div>

      <p v-if="members.length === 0" class="text-gray-500 py-4">
        No members have joined this meeting yet
      </p>
      <p
        v-if="decryptedMembers.length < members.length"
        class="text-center text-red-600 py-4"
      >
        {{
          decryptFailureMessage ||
          "Your password failed. Please go back and try again."
        }}
      </p>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Vue, Prop } from "vue-facing-decorator";

import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "@/db/index";
import {
  errorStringForLog,
  getHeaders,
  serverMessageForUser,
} from "@/libs/endorserServer";
import { decryptMessage } from "@/libs/crypto";

interface Member {
  admitted: boolean;
  content: string;
  memberId: number;
}

interface DecryptedMember {
  member: Member;
  name: string;
  did: string;
}

@Component
export default class MembersList extends Vue {
  @Prop({ required: true }) password!: string;
  @Prop({ default: "Your password failed. Please go back and try again." })
  decryptFailureMessage!: string;

  decryptedMembers: DecryptedMember[] = [];
  missingPassword = false;
  missingMyself = false;
  isLoading = false;
  isOrganizer = false;
  members: Member[] = [];
  activeDid = "";
  apiServer = "";

  async toggleAdmission(member: Member) {
    try {
      const headers = await getHeaders(this.activeDid);
      await this.axios.put(
        `${this.apiServer}/api/partner/groupOnboardMember/${member.memberId}`,
        { admitted: !member.admitted },
        { headers }
      );
      // Update local state
      member.admitted = !member.admitted;
    } catch (error) {
      logConsoleAndDb("Error toggling admission: " + errorStringForLog(error), true);
      this.$emit("error", serverMessageForUser(error) || "Failed to update member admission status.");
    }
  }

  async created() {
    const settings = await retrieveSettingsForActiveAccount();
    this.activeDid = settings.activeDid || "";
    this.apiServer = settings.apiServer || "";
    await this.fetchMembers();
  }

  async fetchMembers() {
    this.isLoading = true;
    try {
      const headers = await getHeaders(this.activeDid);
      const response = await this.axios.get(
        `${this.apiServer}/api/partner/groupOnboardMembers`,
        { headers },
      );

      if (response.data && response.data.data) {
        this.members = response.data.data;
        await this.decryptMemberContents();
      }
    } catch (error) {
      logConsoleAndDb(
        "Error fetching members: " + errorStringForLog(error),
        true,
      );
      this.$emit(
        "error",
        serverMessageForUser(error) || "Failed to fetch members.",
      );
    } finally {
      this.isLoading = false;
    }
  }

  async decryptMemberContents() {
    this.decryptedMembers = [];

    if (!this.password) {
      this.missingPassword = true;
      return;
    }

    let isFirstEntry = true, foundMyself = false;
    for (const member of this.members) {
      try {
        const decryptedContent = await decryptMessage(
          member.content,
          this.password,
        );
        const content = JSON.parse(decryptedContent);

        this.decryptedMembers.push({
          member: member,
          name: content.name,
          did: content.did,
        });
        if (isFirstEntry && content.did === this.activeDid) {
          this.isOrganizer = true;
        }
        if (content.did === this.activeDid) {
          foundMyself = true;
        }
      } catch (error) {
        // do nothing, relying on the count of members to determine if there was an error
      }
      isFirstEntry = false;
    }
    if (!foundMyself) {
      this.missingMyself = true;
    }
  }
}
</script>
