<template>
  <QuickNav selected="Contacts"></QuickNav>
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Breadcrumb -->
    <div class="mb-8">
      <h1
        id="ViewBreadcrumb"
        class="text-lg text-center font-light relative px-7"
      >
        <!-- Back -->
        <router-link
          :to="{ name: 'contacts' }"
          class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
          ><fa icon="chevron-left" class="fa-fw"></fa
        ></router-link>
      </h1>

      <h1 id="ViewHeading" class="text-4xl text-center font-light pt-4">
        Transferred with {{ contact?.name }}
      </h1>
    </div>

    <div class="flex justify-around">
      <span />
      <span class="justify-around">(Only 50 most recent)</span>
      <span />
    </div>
    <div class="flex justify-around">
      <span />
      <span class="justify-around">
        (This does not include claims by them if they're not visible to you.)
      </span>
      <span />
    </div>

    <!-- Results List -->
    <table
      class="table-auto w-full border-t border-slate-300 text-sm sm:text-base text-center"
    >
      <thead class="bg-slate-100">
        <tr class="border-b border-slate-300">
          <th></th>
          <th class="px-1 py-2">From Them</th>
          <th></th>
          <th class="px-1 py-2">To Them</th>
        </tr>
      </thead>
      <tbody>
        <tr
          v-for="record in giveRecords"
          :key="record.id"
          class="border-b border-slate-300"
        >
          <td class="p-1 text-xs sm:text-sm text-left text-slate-500">
            {{ new Date(record.issuedAt).toLocaleString() }}
          </td>
          <td class="p-1">
            <span v-if="record.agentDid == contact?.did">
              <div class="font-bold">
                {{ displayAmount(record.unit, record.amount) }}
                <span v-if="record.amountConfirmed" title="Confirmed">
                  <fa icon="circle-check" class="text-green-600 fa-fw" />
                </span>
                <button v-else @click="confirm(record)" title="Unconfirmed">
                  <fa icon="circle" class="text-blue-600 fa-fw" />
                </button>
              </div>
              <div class="italic text-xs sm:text-sm text-slate-500">
                {{ record.description }}
              </div>
            </span>
          </td>
          <td class="p-1">
            <span v-if="record.agentDid == contact?.did">
              <fa icon="arrow-left" class="text-slate-400 fa-fw" />
            </span>
            <span v-else>
              <fa icon="arrow-right" class="text-slate-400 fa-fw" />
            </span>
          </td>
          <td class="p-1">
            <span v-if="record.agentDid != contact?.did">
              <div class="font-bold">
                {{ displayAmount(record.unit, record.amount) }}
                <span v-if="record.amountConfirmed" title="Confirmed">
                  <fa icon="circle-check" class="text-green-600 fa-fw" />
                </span>
                <button
                  v-else
                  @click="cannotConfirmMessage()"
                  title="Unconfirmed"
                >
                  <fa icon="circle" class="text-slate-600 fa-fw" />
                </button>
              </div>
              <div class="italic text-xs sm:text-sm text-slate-500">
                {{ record.description }}
              </div>
            </span>
          </td>
        </tr>
      </tbody>
    </table>
  </section>
</template>

<script lang="ts">
import { AxiosError, AxiosRequestHeaders } from "axios";
import * as R from "ramda";
import { Component, Vue } from "vue-facing-decorator";
import { Router } from "vue-router";

import QuickNav from "@/components/QuickNav.vue";
import { NotificationIface } from "@/constants/app";
import { accountsDB, db } from "@/db/index";
import { Contact } from "@/db/tables/contacts";
import { MASTER_SETTINGS_KEY } from "@/db/tables/settings";
import {
  AgreeVerifiableCredential,
  createEndorserJwtVcFromClaim,
  displayAmount,
  getHeaders,
  GiveSummaryRecord,
  GiveVerifiableCredential,
  SCHEMA_ORG_CONTEXT,
} from "@/libs/endorserServer";

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

  activeDid = "";
  apiServer = "";
  contact: Contact | null = null;
  giveRecords: Array<GiveSummaryRecord> = [];
  numAccounts = 0;

  displayAmount = displayAmount;

  async beforeCreate() {
    await accountsDB.open();
    this.numAccounts = await accountsDB.accounts.count();
  }

  async created() {
    try {
      await db.open();
      const contactDid = (this.$route as Router).query["contactDid"] as string;
      this.contact = (await db.contacts.get(contactDid)) || null;

      const settings = await db.settings.get(MASTER_SETTINGS_KEY);
      this.activeDid = (settings?.activeDid as string) || "";
      this.apiServer = (settings?.apiServer as string) || "";

      if (this.activeDid && this.contact) {
        this.loadGives(this.activeDid, this.contact);
      }
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
    } catch (err: any) {
      console.error("Error retrieving settings or gives.", err);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text:
            err.userMessage ||
            "There was an error retrieving your settings or contacts or gives.",
        },
        -1,
      );
    }
  }

  async loadGives(activeDid: string, contact: Contact) {
    try {
      let result: Array<GiveSummaryRecord> = [];
      const url =
        this.apiServer +
        "/api/v2/report/gives?agentDid=" +
        encodeURIComponent(this.activeDid) +
        "&recipientDid=" +
        encodeURIComponent(contact.did);
      const headers = await getHeaders(activeDid);
      const resp = await this.axios.get(url, { headers });
      if (resp.status === 200) {
        result = resp.data.data;
      } else {
        console.error(
          "Got bad response status & data of",
          resp.status,
          resp.data,
        );
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error With Server",
            text: "Got an error retrieving your given time from the server.",
          },
          -1,
        );
      }

      const url2 =
        this.apiServer +
        "/api/v2/report/gives?agentDid=" +
        encodeURIComponent(contact.did) +
        "&recipientDid=" +
        encodeURIComponent(this.activeDid);
      const headers2 = await getHeaders(activeDid);
      const resp2 = await this.axios.get(url2, { headers: headers2 });
      if (resp2.status === 200) {
        result = R.concat(result, resp2.data.data);
      } else {
        console.error(
          "Got bad response status & data of",
          resp2.status,
          resp2.data,
        );
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error With Server",
            text: "Got an error retrieving your given time from the server.",
          },
          -1,
        );
      }

      const sortedResult: Array<GiveSummaryRecord> = R.sort(
        (a, b) =>
          new Date(b.issuedAt).getTime() - new Date(a.issuedAt).getTime(),
        result,
      );
      this.giveRecords = sortedResult;
    } catch (error) {
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error With Server",
          text: error as string,
        },
        -1,
      );
    }
  }

  async confirm(record: GiveSummaryRecord) {
    // Make claim
    // I use clone here because otherwise it gets a Proxy object.
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const origClaim: GiveVerifiableCredential = R.clone(record.fullClaim);
    if (record.fullClaim["@context"] == SCHEMA_ORG_CONTEXT) {
      delete origClaim["@context"];
    }
    origClaim["identifier"] = record.handleId;
    const vcClaim: AgreeVerifiableCredential = {
      "@context": SCHEMA_ORG_CONTEXT,
      "@type": "AgreeAction",
      object: origClaim,
    };

    const vcJwt: string = await createEndorserJwtVcFromClaim(
      this.activeDid,
      vcClaim,
    );

    // Make the xhr request payload
    const payload = JSON.stringify({ jwtEncoded: vcJwt });
    const url = this.apiServer + "/api/v2/claim";
    const headers = getHeaders(this.activeDid) as AxiosRequestHeaders;

    try {
      const resp = await this.axios.post(url, payload, { headers });
      if (resp.data?.success) {
        record.amountConfirmed =
          (origClaim.object?.amountOfThisGood as number) || 1;
      }
    } catch (error) {
      let userMessage = "There was an error. See logs for more info.";
      const serverError = error as AxiosError;
      if (serverError) {
        if (serverError.message) {
          userMessage = serverError.message; // Info for the user
        } else {
          userMessage = JSON.stringify(serverError.toJSON());
        }
      } else {
        userMessage = error as string;
      }
      // Now set that error for the user to see.
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error With Server",
          text: userMessage,
        },
        -1,
      );
    }
  }

  cannotConfirmMessage() {
    this.$notify(
      {
        group: "alert",
        type: "danger",
        title: "Not Allowed",
        text: "Only the recipient can confirm final receipt.",
      },
      -1,
    );
  }
}
</script>

<style>
/*
  Tooltip, generated on "title" attributes on "fa" icons
  Kudos to https://www.w3schools.com/css/css_tooltip.asp
*/
/* Tooltip container */
.tooltip {
  position: relative;
  display: inline-block;
  border-bottom: 1px dotted black; /* If you want dots under the hoverable text */
}

/* Tooltip text */
.tooltip .tooltiptext {
  visibility: hidden;
  width: 200px;
  background-color: black;
  color: #fff;
  text-align: center;
  padding: 5px 0;
  border-radius: 6px;

  position: absolute;
  z-index: 1;
}

/* Show the tooltip text when you mouse over the tooltip container */
.tooltip:hover .tooltiptext {
  visibility: visible;
}
.tooltip:hover .tooltiptext-left {
  visibility: visible;
}
</style>
