<template>
  <div v-if="visible" class="dialog-overlay">
    <div class="dialog">
      <div class="text-slate-900 text-center">
        <h3 class="text-lg font-semibold leading-[1.25] mb-2">
          Admit Pending Members
        </h3>
        <p class="text-sm mb-4">
          The following members are waiting to be admitted to the meeting. You
          can choose to admit them and optionally add them as contacts with
          visibility settings.
        </p>

        <!-- Custom table area - you can customize this -->
        <div class="mb-4">
          <table
            class="w-full border-collapse border border-slate-300 text-sm text-start"
          >
            <thead v-if="membersData && membersData.length > 0">
              <tr class="bg-slate-100 font-medium">
                <th class="border border-slate-300 px-3 py-2">
                  <label class="flex items-center gap-2">
                    <input
                      type="checkbox"
                      :checked="isAllSelected"
                      :indeterminate="isIndeterminate"
                      @change="toggleSelectAll"
                    />
                    Select All
                  </label>
                </th>
              </tr>
            </thead>
            <tbody>
              <!-- Dynamic data from MembersList -->
              <tr v-if="!membersData || membersData.length === 0">
                <td
                  class="border border-slate-300 px-3 py-2 text-center italic text-gray-500"
                >
                  No pending members to admit
                </td>
              </tr>
              <tr
                v-for="member in membersData || []"
                :key="member.member.memberId"
              >
                <td class="border border-slate-300 px-3 py-2">
                  <div class="flex items-center justify-between gap-2">
                    <label class="flex items-center gap-2">
                      <input
                        type="checkbox"
                        :checked="isMemberSelected(member.did)"
                        @change="toggleMemberSelection(member.did)"
                      />
                      <div class="">
                        <div class="text-sm font-semibold">
                          {{ member.name || SOMEONE_UNNAMED }}
                        </div>
                        <div
                          class="flex items-center gap-0.5 text-xs text-slate-500"
                        >
                          <span class="font-semibold sm:hidden">DID:</span>
                          <span
                            class="w-[35vw] sm:w-auto truncate text-left"
                            style="direction: rtl"
                            >{{ member.did }}</span
                          >
                        </div>
                      </div>
                    </label>

                    <!-- Contact indicator - only show if they are already a contact -->
                    <font-awesome
                      v-if="member.isContact"
                      icon="user-circle"
                      class="fa-fw ms-auto text-slate-400 cursor-pointer hover:text-slate-600"
                      @click="showContactInfo"
                    />
                  </div>
                </td>
              </tr>
            </tbody>
          </table>
        </div>

        <div class="space-y-2">
          <button
            v-if="membersData && membersData.length > 0"
            :disabled="!hasSelectedMembers"
            :class="[
              'block w-full text-center text-md font-bold uppercase px-2 py-2 rounded-md',
              hasSelectedMembers
                ? 'bg-green-600 text-white cursor-pointer'
                : 'bg-slate-400 text-slate-200 cursor-not-allowed',
            ]"
            @click="admitWithVisibility"
          >
            Admit + Add to Contacts
          </button>
          <button
            class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
            @click="cancel"
          >
            Maybe Later
          </button>
        </div>
      </div>
    </div>
  </div>
</template>

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

import { PlatformServiceMixin } from "@/utils/PlatformServiceMixin";
import { SOMEONE_UNNAMED } from "@/constants/entities";
import { MemberData } from "@/interfaces";
import { setVisibilityUtil, getHeaders } from "@/libs/endorserServer";
import { createNotifyHelpers } from "@/utils/notify";

@Component({
  mixins: [PlatformServiceMixin],
  emits: ["close"],
})
export default class AdmitPendingMembersDialog extends Vue {
  @Prop({ default: "" }) activeDid!: string;
  @Prop({ default: "" }) apiServer!: string;

  // Vue notification system
  $notify!: (
    notification: { group: string; type: string; title: string; text: string },
    timeout?: number,
  ) => void;

  // Notification system
  notify!: ReturnType<typeof createNotifyHelpers>;

  // Component state
  membersData: MemberData[] = [];
  selectedMembers: string[] = [];
  visible = false;

  // Constants
  // In Vue templates, imported constants need to be explicitly made available to the template
  readonly SOMEONE_UNNAMED = SOMEONE_UNNAMED;

  get hasSelectedMembers() {
    return this.selectedMembers.length > 0;
  }

  get isAllSelected() {
    if (!this.membersData || this.membersData.length === 0) return false;
    return this.membersData.every((member) =>
      this.selectedMembers.includes(member.did),
    );
  }

  get isIndeterminate() {
    if (!this.membersData || this.membersData.length === 0) return false;
    const selectedCount = this.membersData.filter((member) =>
      this.selectedMembers.includes(member.did),
    ).length;
    return selectedCount > 0 && selectedCount < this.membersData.length;
  }

  created() {
    this.notify = createNotifyHelpers(this.$notify);
  }

  open(members: MemberData[]) {
    this.visible = true;
    this.membersData = members;
    // Select all by default
    this.selectedMembers = this.membersData.map((member) => member.did);
  }

  close(notSelectedMemberDids: string[]) {
    this.visible = false;
    this.$emit("close", { notSelectedMemberDids: notSelectedMemberDids });
  }

  cancel() {
    this.close(this.membersData.map((member) => member.did));
  }

  toggleSelectAll() {
    if (!this.membersData || this.membersData.length === 0) return;

    if (this.isAllSelected) {
      // Deselect all
      this.selectedMembers = [];
    } else {
      // Select all
      this.selectedMembers = this.membersData.map((member) => member.did);
    }
  }

  toggleMemberSelection(memberDid: string) {
    const index = this.selectedMembers.indexOf(memberDid);
    if (index > -1) {
      this.selectedMembers.splice(index, 1);
    } else {
      this.selectedMembers.push(memberDid);
    }
  }

  isMemberSelected(memberDid: string) {
    return this.selectedMembers.includes(memberDid);
  }

  async admitWithVisibility() {
    try {
      const selectedMembers = this.membersData.filter((member) =>
        this.selectedMembers.includes(member.did),
      );
      const notSelectedMembers = this.membersData.filter(
        (member) => !this.selectedMembers.includes(member.did),
      );

      let admittedCount = 0;
      let contactAddedCount = 0;
      let visibilitySetCount = 0;

      for (const member of selectedMembers) {
        try {
          // First, admit the member
          await this.admitMember(member);
          admittedCount++;

          // If they're not a contact yet, add them as a contact
          if (!member.isContact) {
            await this.addAsContact(member);
            contactAddedCount++;
          }

          // Set their seesMe to true
          await this.updateContactVisibility(member.did, true);
          visibilitySetCount++;
        } catch (error) {
          // eslint-disable-next-line no-console
          console.error(`Error processing member ${member.did}:`, error);
          // Continue with other members even if one fails
        }
      }

      // Show success notification
      this.$notify(
        {
          group: "alert",
          type: "success",
          title: "Members Admitted Successfully",
          text: `Admitted ${admittedCount} member${admittedCount === 1 ? "" : "s"}, added ${contactAddedCount} as contact${contactAddedCount === 1 ? "" : "s"}, and set visibility for ${visibilitySetCount} member${visibilitySetCount === 1 ? "" : "s"}.`,
        },
        10000,
      );

      this.close(notSelectedMembers.map((member) => member.did));
    } catch (error) {
      // eslint-disable-next-line no-console
      console.error("Error admitting members:", error);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "Failed to admit some members. Please try again.",
        },
        5000,
      );
    }
  }

  async admitMember(member: {
    did: string;
    name: string;
    member: { memberId: string };
  }) {
    try {
      const headers = await getHeaders(this.activeDid);
      await this.axios.put(
        `${this.apiServer}/api/partner/groupOnboardMember/${member.member.memberId}`,
        { admitted: true },
        { headers },
      );
    } catch (err) {
      // eslint-disable-next-line no-console
      console.error("Error admitting member:", err);
      throw err;
    }
  }

  async addAsContact(member: { did: string; name: string }) {
    try {
      const newContact = {
        did: member.did,
        name: member.name,
      };

      await this.$insertContact(newContact);
    } catch (err) {
      // eslint-disable-next-line no-console
      console.error("Error adding contact:", err);
      if (err instanceof Error && err.message?.indexOf("already exists") > -1) {
        // Contact already exists, continue
      } else {
        throw err; // Re-throw if it's not a duplicate error
      }
    }
  }

  async updateContactVisibility(did: string, seesMe: boolean) {
    try {
      // Get the contact object
      const contact = await this.$getContact(did);
      if (!contact) {
        throw new Error(`Contact not found for DID: ${did}`);
      }

      // Use the proper API to set visibility on the server
      const result = await setVisibilityUtil(
        this.activeDid,
        this.apiServer,
        this.axios,
        contact,
        seesMe,
      );

      if (!result.success) {
        throw new Error(result.error || "Failed to set visibility");
      }
    } catch (err) {
      // eslint-disable-next-line no-console
      console.error("Error updating contact visibility:", err);
      throw err;
    }
  }

  showContactInfo() {
    this.$notify(
      {
        group: "alert",
        type: "info",
        title: "Contact Info",
        text: "This user is already your contact, but they are not yet admitted to the meeting.",
      },
      5000,
    );
  }
}
</script>

<style scoped>
.dialog-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
}

.dialog {
  background: white;
  border-radius: 8px;
  padding: 24px;
  max-width: 500px;
  width: 90%;
  max-height: 80vh;
  overflow-y: auto;
  box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
}
</style>
