<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">
      Onboarding Meetings
    </h1>

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

    <div v-else-if="attendingMeeting">
      <p>You are in this meeting.</p>
      <div
        class="p-4 bg-white rounded-lg shadow hover:shadow-md transition-shadow cursor-pointer"
        @click="promptPassword(attendingMeeting)"
      >
        <div class="flex justify-between items-center">
          <h2 class="text-xl font-medium">{{ attendingMeeting.name }}</h2>
          <button
            class="text-red-600 hover:text-red-700 p-2"
            title="Leave Meeting"
            @click.stop="leaveMeeting"
          >
            <font-awesome icon="right-from-bracket" />
          </button>
        </div>
      </div>
    </div>

    <!-- Meeting List -->
    <div v-else class="space-y-4">
      <div
        v-for="meeting in meetings"
        :key="meeting.groupId"
        class="p-4 bg-white rounded-lg shadow hover:shadow-md transition-shadow cursor-pointer"
        @click="promptPassword(meeting)"
      >
        <h2 class="text-xl font-medium">{{ meeting.name }}</h2>
      </div>

      <p v-if="meetings.length === 0" class="text-center text-gray-500 py-8">
        No onboarding meetings available
      </p>
    </div>

    <!-- Password Dialog -->
    <div
      v-if="showPasswordDialog"
      class="fixed inset-0 bg-black bg-opacity-50 flex items-center justify-center p-4"
    >
      <div class="bg-white rounded-lg p-6 max-w-sm w-full">
        <h3 class="text-lg font-medium mb-4">Enter Meeting Password</h3>
        <input
          ref="passwordInput"
          v-model="password"
          type="text"
          class="w-full px-3 py-2 border rounded-md mb-4"
          placeholder="Enter password"
          @keyup.enter="submitPassword"
        />
        <div class="flex justify-end space-x-4">
          <button
            class="px-4 py-2 bg-gray-200 rounded hover:bg-gray-300"
            @click="cancelPasswordDialog"
          >
            Cancel
          </button>
          <button
            class="px-4 py-2 bg-blue-600 text-white rounded hover:bg-blue-700"
            @click="submitPassword"
          >
            Submit
          </button>
        </div>
      </div>
    </div>
  </section>
</template>

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

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

interface Meeting {
  name: string;
  groupId: number;
}

@Component({
  components: {
    QuickNav,
    TopMessage,
  },
})
export default class OnboardMeetingListView extends Vue {
  $notify!: (
    notification: {
      group: string;
      type: string;
      title: string;
      text: string;
      onYes?: () => void;
      yesText?: string;
    },
    timeout?: number,
  ) => void;
  $router!: Router;

  activeDid = "";
  apiServer = "";
  attendingMeeting: Meeting | null = null;
  firstName = "";
  isLoading = false;
  isRegistered = false;
  meetings: Meeting[] = [];
  password = "";
  selectedMeeting: Meeting | null = null;
  showPasswordDialog = false;

  async created() {
    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;
    await this.fetchMeetings();
  }

  async fetchMeetings() {
    this.isLoading = true;
    try {
      // get the meeting that the user is attending
      const headers = await getHeaders(this.activeDid);
      const response = await this.axios.get(
        this.apiServer + "/api/partner/groupOnboardMember",
        { headers },
      );

      if (response.data?.data) {
        // they're in a meeting already
        const attendingMeetingId = response.data.data.groupId;
        // retrieve the meeting details
        const headers2 = await getHeaders(this.activeDid);
        const response2 = await this.axios.get(
          this.apiServer + "/api/partner/groupOnboard/" + attendingMeetingId,
          { headers: headers2 },
        );

        if (response2.data?.data) {
          this.attendingMeeting = response2.data.data;
          return;
        } else {
          // this should never happen
          logConsoleAndDb(
            "Error fetching meeting for user after saying they are in one.",
            true,
          );
        }
      }

      const headers2 = await getHeaders(this.activeDid);
      const response2 = await this.axios.get(
        this.apiServer + "/api/partner/groupsOnboarding",
        { headers: headers2 },
      );

      if (response2.data?.data) {
        this.meetings = response2.data.data;
      }
    } catch (error) {
      logConsoleAndDb(
        "Error fetching meetings: " + errorStringForLog(error),
        true,
      );
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: serverMessageForUser(error) || "Failed to fetch meetings.",
        },
        5000,
      );
    } finally {
      this.isLoading = false;
    }
  }

  promptPassword(meeting: Meeting) {
    this.password = "";
    this.selectedMeeting = meeting;
    this.showPasswordDialog = true;
    nextTick(() => {
      const input = this.$refs.passwordInput as HTMLInputElement;
      if (input) {
        input.focus();
      }
    });
  }

  cancelPasswordDialog() {
    this.password = "";
    this.selectedMeeting = null;
    this.showPasswordDialog = false;
  }

  async submitPassword() {
    if (!this.selectedMeeting) {
      // this should never happen
      logConsoleAndDb(
        "No meeting selected when prompting for password, which should never happen.",
        true,
      );
      return;
    }

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

      // Get headers for authentication
      const headers = await getHeaders(this.activeDid);

      // Encrypt the member data
      const postResult = await this.axios.post(
        this.apiServer + "/api/partner/groupOnboardMember",
        {
          groupId: this.selectedMeeting.groupId,
          content: encryptedMemberData,
        },
        { headers },
      );

      if (postResult.data && postResult.data.success) {
        // Navigate to members view with password and groupId
        this.$router.push({
          name: "onboard-meeting-members",
          params: {
            groupId: this.selectedMeeting.groupId.toString(),
          },
          query: {
            password: this.password,
            memberId: postResult.data.memberId,
          },
        });

        this.cancelPasswordDialog();
      } else {
        throw { response: postResult };
      }
    } catch (error) {
      logConsoleAndDb(
        "Error joining meeting: " + errorStringForLog(error),
        true,
      );
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text:
            serverMessageForUser(error) || "You failed to join the meeting.",
        },
        5000,
      );
    }
  }

  async leaveMeeting() {
    this.$notify(
      {
        group: "modal",
        type: "confirm",
        title: "Leave Meeting",
        text: "Are you sure you want to leave this meeting?",
        onYes: async () => {
          try {
            const headers = await getHeaders(this.activeDid);
            await this.axios.delete(
              this.apiServer + "/api/partner/groupOnboardMember",
              { headers },
            );

            this.attendingMeeting = null;
            await this.fetchMeetings();

            this.$notify(
              {
                group: "alert",
                type: "success",
                title: "Success",
                text: "You left the meeting.",
              },
              5000,
            );
          } catch (error) {
            logConsoleAndDb(
              "Error leaving meeting: " + errorStringForLog(error),
              true,
            );
            this.$notify(
              {
                group: "alert",
                type: "danger",
                title: "Error",
                text:
                  serverMessageForUser(error) ||
                  "You failed to leave the meeting.",
              },
              5000,
            );
          }
        },
      },
      -1,
    );
  }
}
</script>
