<template>
  <QuickNav />
  <!-- CONTENT -->
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Heading -->
    <h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
      Image
    </h1>
    <div v-if="imageBlob">
      <div v-if="uploading" class="text-center mb-4">
        <font-awesome icon="spinner" class="fa-spin-pulse" />
      </div>
      <div v-else>
        <div class="text-center mb-4">Choose how to use this image</div>
        <div class="grid grid-cols-1 sm:grid-cols-3 gap-4">
          <button
            class="text-center text-md font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md"
            @click="recordGift"
          >
            <font-awesome icon="gift" class="fa-fw" />
            Record a Gift
          </button>
          <button
            class="text-center text-md font-bold bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md"
            @click="recordProfile"
          >
            <font-awesome icon="circle-user" class="fa-fw" />
            Save as Profile Image
          </button>
          <button
            class="text-center text-md font-bold bg-gradient-to-b from-slate-400 to-slate-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-2 py-3 rounded-md"
            @click="cancel"
          >
            <font-awesome icon="ban" class="fa-fw" />
            Cancel
          </button>
        </div>
        <PhotoDialog ref="photoDialog" />
      </div>

      <div class="flex justify-center">
        <img
          :src="URL.createObjectURL(imageBlob)"
          alt="Shared Image"
          class="rounded mt-4"
        />
      </div>
    </div>
    <div v-else class="text-center mb-4">
      <p>No image found.</p>
      <p class="mt-4">
        If you shared an image, the cause is usually that you do not have the
        recent version of this app, or that the app has not refreshed the
        service code underneath. To fix this, first make sure you have latest
        version by comparing your version at the bottom of "Help" with the
        version at the bottom of https://timesafari.app/help in a browser. After
        that, it may eventually work, but you can speed up the process by
        clearing your data cache (in the browser on mobile, even if you
        installed it) and/or reinstalling the app (after backing up all your
        data, of course).
      </p>
    </div>
  </section>
</template>

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

import PhotoDialog from "../components/PhotoDialog.vue";
import QuickNav from "../components/QuickNav.vue";
import {
  DEFAULT_IMAGE_API_SERVER,
  IMAGE_TYPE_PROFILE,
  NotificationIface,
  USE_DEXIE_DB,
} from "../constants/app";
import * as databaseUtil from "../db/databaseUtil";
import { db, retrieveSettingsForActiveAccount } from "../db/index";
import { MASTER_SETTINGS_KEY } from "../db/tables/settings";
import { accessToken } from "../libs/crypto";
import { base64ToBlob, SHARED_PHOTO_BASE64_KEY } from "../libs/util";
import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "@/services/PlatformServiceFactory";
import { Temp } from "@/db/tables/temp";
@Component({ components: { PhotoDialog, QuickNav } })
export default class SharedPhotoView extends Vue {
  $notify!: (notification: NotificationIface, timeout?: number) => void;
  $router!: Router;
  $route!: RouteLocationNormalizedLoaded;

  activeDid: string | undefined = undefined;
  imageBlob: Blob | undefined = undefined;
  imageFileName: string | undefined = undefined;
  uploading = false;

  URL = window.URL || window.webkitURL;

  // 'created' hook runs when the Vue instance is first created
  async mounted() {
    try {
      let settings = await databaseUtil.retrieveSettingsForActiveAccount();
      if (USE_DEXIE_DB) {
        settings = await retrieveSettingsForActiveAccount();
      }
      this.activeDid = settings.activeDid;

      const platformService = PlatformServiceFactory.getInstance();
      const tempQuery = await platformService.dbQuery(
        "SELECT * FROM temp WHERE id = ?",
        [SHARED_PHOTO_BASE64_KEY],
      );
      let temp = databaseUtil.mapQueryResultToValues(tempQuery)?.[0] as Temp;
      if (USE_DEXIE_DB) {
        temp = (await db.temp.get(SHARED_PHOTO_BASE64_KEY)) as unknown as Temp;
      }
      const imageB64 = temp?.blobB64 as string;
      if (temp) {
        this.imageBlob = base64ToBlob(imageB64);

        // clear the temp image
        await platformService.dbExec("DELETE FROM temp WHERE id = ?", [
          SHARED_PHOTO_BASE64_KEY,
        ]);
        if (USE_DEXIE_DB) {
          await db.temp.delete(SHARED_PHOTO_BASE64_KEY);
        }

        this.imageFileName = this.$route.query["fileName"] as string;
      } else {
        logger.error("No appropriate image found in temp storage.", temp);
      }
    } catch (err: unknown) {
      logger.error("Got an error loading an identifier:", err);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: "Got an error loading this data.",
        },
        3000,
      );
    }
  }

  async recordGift() {
    await this.sendToImageServer("GiveAction").then((url) => {
      if (url) {
        const route = {
          name: "gifted-details",
          // this might be wrong since "name" goes with params, but it works so test well when you change it
          query: {
            destinationPathAfter: "/",
            hideBackButton: "true",
            imageUrl: url,
            recipientDid: this.activeDid,
          },
        } as RouteLocationRaw;
        this.$router.push(route);
      }
    });
  }

  recordProfile() {
    (this.$refs.photoDialog as PhotoDialog).open(
      async (imgUrl) => {
        databaseUtil.updateDefaultSettings({ profileImageUrl: imgUrl });
        if (USE_DEXIE_DB) {
          await db.settings.update(MASTER_SETTINGS_KEY, {
            profileImageUrl: imgUrl,
          });
        }
        this.$router.push({ name: "account" });
      },
      IMAGE_TYPE_PROFILE,
      true,
      this.imageBlob,
      this.imageFileName,
    );
  }

  async cancel() {
    this.imageBlob = undefined;
    this.imageFileName = undefined;
    this.$router.push({ name: "home" });
  }

  async sendToImageServer(imageType: string) {
    this.uploading = true;

    let result;
    try {
      // send the image to the server
      const token = await accessToken(this.activeDid);
      const headers = {
        Authorization: "Bearer " + token,
        // axios fills in Content-Type of multipart/form-data
      };
      const formData = new FormData();
      formData.append(
        "image",
        this.imageBlob as Blob,
        this.imageFileName as string,
      );
      formData.append("claimType", imageType);

      if (
        window.location.hostname === "localhost" &&
        !DEFAULT_IMAGE_API_SERVER.includes("localhost")
      ) {
        logger.log(
          "Using shared image API server, so only users on that server can play with images.",
        );
      }
      const response = await axios.post(
        DEFAULT_IMAGE_API_SERVER + "/image",
        formData,
        { headers },
      );
      if (response?.data?.url) {
        this.imageBlob = undefined;
        this.imageFileName = undefined;
        result = response.data.url as string;
      } else {
        logger.error("Problem uploading the image", response.data);
        this.$notify(
          {
            group: "alert",
            type: "danger",
            title: "Error",
            text:
              "There was a problem saving the picture. " +
              (response?.data?.message || ""),
          },
          5000,
        );
      }

      this.uploading = false;
    } catch (error) {
      // Log the raw error first
      logger.error("Raw error object:", JSON.stringify(error, null, 2));

      let errorMessage = "There was an error saving the picture.";

      if (axios.isAxiosError(error)) {
        const status = error.response?.status;
        const statusText = error.response?.statusText;
        const data = error.response?.data;

        // Log detailed error information
        logger.error("Upload error details:", {
          status,
          statusText,
          data: JSON.stringify(data, null, 2),
          message: error.message,
          config: {
            url: error.config?.url,
            method: error.config?.method,
            headers: error.config?.headers,
          },
        });

        if (status === 401) {
          errorMessage = "Authentication failed. Please try logging in again.";
        } else if (status === 413) {
          errorMessage = "Image file is too large. Please try a smaller image.";
        } else if (status === 415) {
          errorMessage =
            "Unsupported image format. Please try a different image.";
        } else if (status && status >= 500) {
          errorMessage = "Server error. Please try again later.";
        } else if (data?.message) {
          errorMessage = data.message;
        }
      } else if (error instanceof Error) {
        // Log non-Axios error with full details
        logger.error("Non-Axios error details:", {
          name: error.name,
          message: error.message,
          stack: error.stack,
          error: JSON.stringify(error, Object.getOwnPropertyNames(error), 2),
        });
      } else {
        // Log any other type of error
        logger.error("Unknown error type:", {
          error: JSON.stringify(error, null, 2),
          type: typeof error,
        });
      }

      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Error",
          text: errorMessage,
        },
        5000,
      );
      this.uploading = false;
    }
    return result;
  }
}
</script>
