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

  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Back -->
    <div class="text-lg text-center font-light relative px-7">
      <h1
        class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
        @click="$router.back()"
      >
        <fa icon="chevron-left" class="fa-fw"></fa>
      </h1>
    </div>

    <!-- Heading -->
    <h1 class="text-4xl text-center font-light">Invitations</h1>

    <!-- New Project -->
    <button
      v-if="isRegistered"
      class="fixed right-6 top-12 text-center text-4xl leading-none bg-blue-600 text-white w-14 py-2.5 rounded-full"
      @click="createInvite()"
    >
      <fa icon="plus" class="fa-fw"></fa>
    </button>

    <InviteDialog ref="inviteDialog" />

    <!-- Invites Table -->
    <div v-if="invites.length" class="mt-6">
      <table class="min-w-full bg-white">
        <thead>
          <tr>
            <th class="py-2">ID</th>
            <th class="py-2">Notes</th>
            <th class="py-2">Expires At</th>
            <th class="py-2">Redeemed By</th>
          </tr>
        </thead>
        <tbody>
          <tr
            v-for="invite in invites"
            :key="invite.inviteIdentifier"
            class="border-t"
          >
            <td class="py-2 text-center">
              {{ getTruncatedInviteId(invite.inviteIdentifier) }}
            </td>
            <td class="py-2 text-left">{{ invite.notes }}</td>
            <td class="py-2 text-center">
              {{ invite.expiresAt.substring(0, 10) }}
            </td>
            <td class="py-2 text-center">
              {{ getTruncatedRedeemedBy(invite.redeemedBy) }}
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <p v-else class="mt-6 text-center">No invites found.</p>
  </section>
</template>
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import axios from "axios";

import { db, retrieveSettingsForActiveAccount } from "../db";
import QuickNav from "@/components/QuickNav.vue";
import TopMessage from "@/components/TopMessage.vue";
import InviteDialog from "@/components/InviteDialog.vue";
import { NotificationIface } from "@/constants/app";
import { createInviteJwt, getHeaders } from "@/libs/endorserServer";

interface Invite {
  inviteIdentifier: string;
  expiresAt: string;
  notes: string;
  redeemedBy: string | null;
}

@Component({
  components: { QuickNav, TopMessage, InviteDialog },
})
export default class InviteOneView extends Vue {
  $notify!: (notification: NotificationIface, timeout?: number) => void;

  invites: Invite[] = [];
  activeDid: string = "";
  apiServer: string = "";
  isRegistered: boolean = false;

  async mounted() {
    try {
      await db.open();
      const settings = await retrieveSettingsForActiveAccount();
      this.activeDid = settings.activeDid || "";
      this.apiServer = settings.apiServer || "";
      this.isRegistered = !!settings.isRegistered;

      const headers = await getHeaders(this.activeDid);
      const response = await axios.get(
        this.apiServer + "/api/userUtil/invite",
        { headers },
      );
      this.invites = response.data.data;
    } catch (error) {
      console.error("Error fetching invites:", error);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Load Error",
          text: "Got an error loading your invites.",
        },
        5000,
      );
    }
  }

  getTruncatedInviteId(inviteId: string): string {
    if (inviteId.length <= 9) return inviteId;
    return `${inviteId.slice(0, 3)}...${inviteId.slice(-3)}`;
  }

  getTruncatedRedeemedBy(redeemedBy: string | null): string {
    if (!redeemedBy) return "Not yet redeemed";
    if (redeemedBy.length <= 19) return redeemedBy;
    return `${redeemedBy.slice(0, 13)}...${redeemedBy.slice(-3)}`;
  }

  async createInvite() {
    (this.$refs.inviteDialog as InviteDialog).open(
      "Invitation Note",
      `These notes are only for your use, to make comments for a link to recall later if redeemed by someone. 
       Note that this is sent to the server.`,
      async (notes, expiresAt) => {
        try {
          const inviteIdentifier =
            Math.random().toString(36).substring(2) +
            Math.random().toString(36).substring(2) +
            Math.random().toString(36).substring(2);
          const headers = await getHeaders(this.activeDid);
          if (!expiresAt) {
            throw {
              response: {
                data: { error: "You must select an expiration date." },
              },
            };
          }
          const expiresIn =
            (new Date(expiresAt).getTime() - new Date().getTime()) / 1000;
          const inviteJwt = await createInviteJwt(
            this.activeDid,
            undefined,
            inviteIdentifier,
            expiresIn,
          );
          await axios.post(
            this.apiServer + "/api/userUtil/invite",
            { inviteJwt: inviteJwt, notes: notes },
            { headers },
          );
          this.invites.push({
            inviteIdentifier: inviteIdentifier,
            expiresAt: expiresAt,
            notes: notes,
            redeemedBy: null,
          });
          // eslint-disable-next-line @typescript-eslint/no-explicit-any
        } catch (error: any) {
          console.error("Error creating invite:", error);
          let message = "Got an error creating your invite.";
          if (
            error.response &&
            error.response.data &&
            error.response.data.error
          ) {
            message = error.response.data.error;
          }
          this.$notify(
            {
              group: "alert",
              type: "danger",
              title: "Error Creating Invite",
              text: message,
            },
            5000,
          );
        }
      },
    );
  }
}
</script>
