<template>
  <section id="Content">
    <div class="flex items-center justify-center h-screen">
      <div v-if="claimData">
        <router-link :to="'/claim/' + claimId">
          <canvas ref="claimCanvas" class="w-full block mx-auto"></canvas>
        </router-link>
      </div>
    </div>
  </section>
</template>

<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";
import { nextTick } from "vue";
import QRCode from "qrcode";
import { APP_SERVER, NotificationIface, USE_DEXIE_DB } from "../constants/app";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import * as databaseUtil from "../db/databaseUtil";
import * as serverUtil from "../libs/endorserServer";
import { GenericCredWrapper, GenericVerifiableCredential } from "../interfaces";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Contact } from "@/db/tables/contacts";
@Component
export default class ClaimCertificateView extends Vue {
  $notify!: (notification: NotificationIface, timeout?: number) => void;

  activeDid = "";
  allMyDids: Array<string> = [];
  apiServer = "";
  claimId = "";
  claimData = null;

  serverUtil = serverUtil;

  async created() {
    let settings = await databaseUtil.retrieveSettingsForActiveAccount();
    if (USE_DEXIE_DB) {
      settings = await retrieveSettingsForActiveAccount();
    }
    this.activeDid = settings.activeDid || "";
    this.apiServer = settings.apiServer || "";
    const pathParams = window.location.pathname.substring(
      "/claim-cert/".length,
    );
    this.claimId = pathParams;
    await this.fetchClaim();
  }

  async fetchClaim() {
    try {
      const headers = await serverUtil.getHeaders(this.activeDid);
      const response = await this.axios.get(
        `${this.apiServer}/api/claim/${this.claimId}`,
        { headers },
      );
      if (response.status === 200) {
        this.claimData = await response.data;
        const claimEntryIds = [this.claimId];
        const headers = await serverUtil.getHeaders(this.activeDid);
        const confirmerResponse = await this.axios.post(
          `${this.apiServer}/api/v2/report/confirmers/?claimEntryIds=${this.claimId}`,
          { claimEntryIds },
          { headers },
        );
        let confirmerIds: Array<string> = [];
        if (confirmerResponse.status === 200) {
          confirmerIds = await confirmerResponse.data.data;
        }
        await nextTick(); // Wait for the DOM to update
        if (this.claimData) {
          this.drawCanvas(this.claimData, confirmerIds);
        }
      } else {
        throw new Error(`Error fetching claim: ${response.statusText}`);
      }
    } catch (error) {
      logger.error("Failed to load claim:", error);
      this.$notify({
        group: "alert",
        type: "danger",
        title: "Error",
        text: "There was a problem loading the claim.",
      });
    }
  }

  async drawCanvas(
    claimData: GenericCredWrapper<GenericVerifiableCredential>,
    confirmerIds: Array<string>,
  ) {
    const platformService = PlatformServiceFactory.getInstance();
    const dbAllContacts = await platformService.dbQuery(
      "SELECT * FROM contacts",
    );
    let allContacts = databaseUtil.mapQueryResultToValues(
      dbAllContacts,
    ) as unknown as Contact[];
    if (USE_DEXIE_DB) {
      await db.open();
      allContacts = await db.contacts.toArray();
    }

    const canvas = this.$refs.claimCanvas as HTMLCanvasElement;
    if (canvas) {
      const CANVAS_WIDTH = 1100;
      const CANVAS_HEIGHT = 850;

      // size to approximate portrait of 8.5"x11"
      canvas.width = CANVAS_WIDTH;
      canvas.height = CANVAS_HEIGHT;
      const ctx = canvas.getContext("2d");
      if (ctx) {
        // Load the background image
        const backgroundImage = new Image();
        backgroundImage.src = "/img/background/cert-frame-2.jpg";
        backgroundImage.onload = async () => {
          // Draw the background image
          ctx.drawImage(backgroundImage, 0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);

          // Set font and styles
          ctx.fillStyle = "black";

          // Draw claim type
          ctx.font = "bold 20px Arial";
          const claimTypeText =
            claimData.claimType === "GiveAction"
              ? "Gift"
              : claimData.claimType === "PlanAction"
                ? "Project"
                : this.serverUtil.capitalizeAndInsertSpacesBeforeCaps(
                    claimData.claimType || "",
                  );
          const claimTypeWidth = ctx.measureText(claimTypeText).width;
          ctx.fillText(
            claimTypeText,
            (CANVAS_WIDTH - claimTypeWidth) / 2, // Center horizontally
            CANVAS_HEIGHT * 0.33,
          );

          if (claimData.claimType === "GiveAction" && claimData.claim.agent) {
            const presentedText = "Thanks To";
            ctx.font = "14px Arial";
            const presentedWidth = ctx.measureText(presentedText).width;
            ctx.fillText(
              presentedText,
              (CANVAS_WIDTH - presentedWidth) / 2, // Center horizontally
              CANVAS_HEIGHT * 0.37,
            );
            const agentDid =
              claimData.claim.agent.identifier || claimData.claim.agent;
            const agentText = serverUtil.didInfoForCertificate(
              agentDid,
              allContacts,
            );
            ctx.font = "bold 20px Arial";
            const agentWidth = ctx.measureText(agentText).width;
            ctx.fillText(
              agentText,
              (CANVAS_WIDTH - agentWidth) / 2, // Center horizontally
              CANVAS_HEIGHT * 0.41,
            );
          }

          // alternatively, show some offer details
          if (claimData.claimType === "Offer") {
            const presentedText = "To";
            ctx.font = "14px Arial";
            const presentedWidth = ctx.measureText(presentedText).width;
            ctx.fillText(
              presentedText,
              (CANVAS_WIDTH - presentedWidth) / 2, // Center horizontally
              CANVAS_HEIGHT * 0.37,
            );
            // fulfills
            const agentDid =
              claimData.claim.agent.identifier || claimData.claim.agent;
            const agentText = serverUtil.didInfoForCertificate(
              agentDid,
              allContacts,
            );
            ctx.font = "bold 20px Arial";
            const agentWidth = ctx.measureText(agentText).width;
            ctx.fillText(
              agentText,
              (CANVAS_WIDTH - agentWidth) / 2, // Center horizontally
              CANVAS_HEIGHT * 0.41,
            );
          }

          const descriptionText =
            claimData.claim.name ||
            claimData.claim.description ||
            claimData.claim.itemOffered?.description; // for Offers
          if (descriptionText) {
            const descriptionLine =
              descriptionText.length > 50
                ? descriptionText.substring(0, 75) + "..."
                : descriptionText;
            ctx.font = "14px Arial";
            const descriptionWidth = ctx.measureText(descriptionLine).width;
            ctx.fillText(
              descriptionLine,
              (CANVAS_WIDTH - descriptionWidth) / 2,
              CANVAS_HEIGHT * 0.495,
            );
          }

          const possibleObject =
            claimData.claim.object || // for GiveActions
            claimData.claim.includesObject; // for Offers
          if (possibleObject?.amountOfThisGood && possibleObject?.unitCode) {
            const amount = possibleObject.amountOfThisGood;
            const unit = possibleObject.unitCode;
            const amountText = serverUtil.displayAmount(unit, amount);
            const amountWidth = ctx.measureText(amountText).width;
            // if there was no description then put this in that spot, otherwise put it below the description
            const yPos = descriptionText
              ? CANVAS_HEIGHT * 0.525
              : CANVAS_HEIGHT * 0.495;
            ctx.font = "14px Arial";
            ctx.fillText(amountText, (CANVAS_WIDTH - amountWidth) / 2, yPos);
          }

          // Draw claim issuer
          if (
            claimData.issuer == null ||
            serverUtil.isHiddenDid(claimData.issuer) ||
            // don't show if issuer claimed for themselves
            // (The confirmations are the good stuff anyway, and self-issued certs shouldn't detract from that.)
            claimData.issuer !== claimData.claim.agent?.identifier
          ) {
            ctx.font = "14px Arial";
            let fullIssuer = serverUtil.didInfoForCertificate(
              claimData.issuer,
              allContacts,
            );
            if (fullIssuer.length > 30) {
              fullIssuer = fullIssuer.substring(0, 30) + "...";
            }
            const issuerText = "Issued by " + fullIssuer;
            ctx.fillText(issuerText, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.6);
          }

          // Draw number of claim confirmers
          if (confirmerIds.length > 0) {
            const confirmerText =
              "Confirmed by " +
              confirmerIds.length +
              (confirmerIds.length === 1 ? " person" : " people");
            ctx.font = "14px Arial";
            ctx.fillText(
              confirmerText,
              CANVAS_WIDTH * 0.3,
              CANVAS_HEIGHT * 0.63,
            );
          }

          // Draw claim ID
          ctx.font = "14px Arial";
          ctx.fillText(this.claimId, CANVAS_WIDTH * 0.3, CANVAS_HEIGHT * 0.7);
          ctx.fillText(
            "via EndorserSearch.com",
            CANVAS_WIDTH * 0.3,
            CANVAS_HEIGHT * 0.73,
          );

          // Generate and draw QR code
          const qrCodeCanvas = document.createElement("canvas");
          await QRCode.toCanvas(
            qrCodeCanvas,
            APP_SERVER + "/claim/" + this.claimId,
            {
              width: 150,
              color: { light: "#0000" /* Transparent background */ },
            },
          );
          ctx.drawImage(qrCodeCanvas, CANVAS_WIDTH * 0.6, CANVAS_HEIGHT * 0.55);
        };
      }
    }
  }
}
</script>
