<template>
  <QuickNav selected="Contacts" />
  <TopMessage />

  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Heading -->
    <h1 id="ViewHeading" class="text-4xl text-center font-light mb-8">
      Meeting Members
    </h1>

    <!-- Loading Animation -->
    <div
      v-if="isLoading"
      class="mt-16 text-center text-4xl bg-slate-400 text-white w-14 py-2.5 rounded-full mx-auto"
    >
      <font-awesome icon="spinner" class="fa-spin-pulse"></font-awesome>
    </div>

    <!-- Error State -->
    <div v-else-if="errorMessage">
      <div class="text-center text-red-600 py-8">
        {{ errorMessage }}
      </div>
      <div class="text-center">
        For authorization, wait for your meeting organizer to approve you.
      </div>
    </div>

    <!-- Members List -->
    <MembersList v-else :password="password" @error="handleError" />

    <!-- Project Link Section -->
    <div v-if="projectLink" class="mt-8 p-4 border rounded-lg bg-white shadow">
      <router-link
        :to="'/project/' + encodeURIComponent(projectLink)"
        class="text-blue-600 hover:text-blue-800 transition-colors duration-200"
      >
        Go To Project Page
      </router-link>
    </div>
  </section>

  <UserNameDialog
    ref="userNameDialog"
    :callback-on-cancel="true"
    sharing-explanation="This is encrypted and shared only with people in this meeting."
  />
</template>

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

import QuickNav from "../components/QuickNav.vue";
import TopMessage from "../components/TopMessage.vue";
import MembersList from "../components/MembersList.vue";
import UserNameDialog from "../components/UserNameDialog.vue";
import * as databaseUtil from "../db/databaseUtil";
import { retrieveSettingsForActiveAccount } from "../db/index";
import { logConsoleAndDb } from "../db/databaseUtil";
import { encryptMessage } from "../libs/crypto";
import {
  errorStringForLog,
  getHeaders,
  serverMessageForUser,
} from "../libs/endorserServer";
import { generateSaveAndActivateIdentity } from "../libs/util";
import { USE_DEXIE_DB } from "@/constants/app";

@Component({
  components: {
    QuickNav,
    TopMessage,
    MembersList,
    UserNameDialog,
  },
})
export default class OnboardMeetingMembersView extends Vue {
  activeDid = "";
  apiServer = "";
  errorMessage = "";
  firstName = "";
  isRegistered = false;
  isLoading = true;
  projectLink = "";
  $route!: RouteLocationNormalizedLoaded;
  $router!: Router;

  userNameDialog!: InstanceType<typeof UserNameDialog>;

  get groupId(): string {
    return (this.$route.params.groupId as string) || "";
  }

  get password(): string {
    return (this.$route.query.password as string) || "";
  }

  async created() {
    if (!this.groupId) {
      this.errorMessage = "The group info is missing. Go back and try again.";
      this.isLoading = false;
      return;
    }
    if (!this.password) {
      this.errorMessage = "The password is missing. Go back and try again.";
      this.isLoading = false;
      return;
    }
    let settings = await databaseUtil.retrieveSettingsForActiveAccount();
    if (USE_DEXIE_DB) {
      settings = await retrieveSettingsForActiveAccount();
    }
    this.activeDid = settings.activeDid || "";
    this.apiServer = settings.apiServer || "";
    this.firstName = settings.firstName || "";
    this.isRegistered = settings.isRegistered || false;
    try {
      if (!this.activeDid) {
        this.activeDid = await generateSaveAndActivateIdentity();
        this.isRegistered = false;
      }
      const headers = await getHeaders(this.activeDid);
      const response = await this.axios.get(
        `${this.apiServer}/api/partner/groupOnboardMember`,
        { headers },
      );
      const member = response.data?.data;
      if (!member) {
        if (!this.firstName) {
          this.$refs.userNameDialog.open(this.addMemberToMeeting);
          // addMemberToMeeting sets isLoading to false
        } else {
          await this.addMemberToMeeting(this.firstName);
          // addMemberToMeeting sets isLoading to false
        }
      } else if (String(member.groupId) !== this.groupId) {
        this.errorMessage =
          "You are already in a different meeting. Reload or go back and try again.";
        this.isLoading = false;
      } else {
        // must be already in the right meeting
        if (!this.firstName) {
          this.$refs.userNameDialog.open(this.updateMemberInMeeting);
          // updateMemberInMeeting sets isLoading to false
        } else {
          await this.updateMemberInMeeting(this.firstName);
          // updateMemberInMeeting sets isLoading to false
        }
      }

      // Fetch the meeting details to get the project link
      const meetingResponse = await this.axios.get(
        `${this.apiServer}/api/partner/groupOnboard/${this.groupId}`,
        { headers },
      );
      if (meetingResponse.data?.data?.projectLink) {
        this.projectLink = meetingResponse.data.data.projectLink;
      }
    } catch (error) {
      this.errorMessage =
        serverMessageForUser(error) ||
        "There was an error checking for that meeting. Reload or go back and try again.";
      logConsoleAndDb(
        "Error checking meeting: " + errorStringForLog(error),
        true,
      );
      this.isLoading = false;
    }
  }

  async addMemberToMeeting(name?: string) {
    if (name != null) {
      this.firstName = name;
    }

    const memberData = {
      name: this.firstName,
      did: this.activeDid,
      isRegistered: this.isRegistered,
    };
    const memberDataString = JSON.stringify(memberData);
    const encryptedMemberData = await encryptMessage(
      memberDataString,
      this.password,
    );

    const headers = await getHeaders(this.activeDid);
    try {
      await this.axios.post(
        `${this.apiServer}/api/partner/groupOnboardMember`,
        { groupId: this.groupId, content: encryptedMemberData },
        { headers },
      );
    } catch (error) {
      logConsoleAndDb(
        "Error adding member to meeting: " + errorStringForLog(error),
        true,
      );
      this.errorMessage =
        serverMessageForUser(error) ||
        "You're not in a meeting and couldn't be added to this one. Reload or go back and try again.";
    }
    this.isLoading = false;
  }

  async updateMemberInMeeting(name?: string) {
    if (name != null) {
      this.firstName = name;
    }
    const memberData = {
      name: this.firstName,
      did: this.activeDid,
      isRegistered: this.isRegistered,
    };
    const memberDataString = JSON.stringify(memberData);
    const encryptedMemberData = await encryptMessage(
      memberDataString,
      this.password,
    );
    const headers = await getHeaders(this.activeDid);
    try {
      await this.axios.put(
        `${this.apiServer}/api/partner/groupOnboardMember`,
        { content: encryptedMemberData },
        { headers },
      );
    } catch (error) {
      logConsoleAndDb(
        "Error updating member in meeting: " + errorStringForLog(error),
        true,
      );
      this.errorMessage =
        serverMessageForUser(error) ||
        "There was an error updating your name. Reload or go back and try again.";
    }
    this.isLoading = false;
  }

  handleError(message: string) {
    this.errorMessage = message;
  }
}
</script>
