/** * Data Export Section Component * * Provides UI and functionality for
exporting user data and backing up identifier seeds. * Includes buttons for seed
backup and database export, with platform-specific download instructions. * *
@component * @displayName DataExportSection * @example * ```vue *
<DataExportSection :active-did="currentDid" />
* ``` */

<template>
  <div
    id="sectionDataExport"
    class="bg-slate-100 rounded-md overflow-hidden px-4 py-4 mt-8 mb-8"
  >
    <div class="mb-2 font-bold">Data Export</div>
    <router-link
      v-if="activeDid"
      :to="{ name: 'seed-backup' }"
      class="block w-full text-center text-md 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-1.5 py-2 rounded-md mb-2 mt-2"
    >
      Backup Identifier Seed
    </router-link>

    <button
      :class="computedStartDownloadLinkClassNames()"
      class="block w-full text-center text-md 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-1.5 py-2 rounded-md"
      @click="exportDatabase()"
    >
      Download Contacts
    </button>
    <a
      ref="downloadLink"
      :class="computedDownloadLinkClassNames()"
      class="block w-full text-center text-md bg-gradient-to-b from-green-500 to-green-800 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] text-white px-1.5 py-2 rounded-md mb-6"
    >
      If no download happened yet, click again here to download now.
    </a>
    <div v-if="platformCapabilities.needsFileHandlingInstructions" class="mt-4">
      <p>
        After the download, you can save the file in your preferred storage
        location.
      </p>
      <ul>
        <li
          v-if="platformCapabilities.isIOS"
          class="list-disc list-outside ml-4"
        >
          On iOS: You will be prompted to choose a location to save your backup
          file.
        </li>
        <li
          v-if="platformCapabilities.isMobile && !platformCapabilities.isIOS"
          class="list-disc list-outside ml-4"
        >
          On Android: You will be prompted to choose a location to save your
          backup file.
        </li>
      </ul>
    </div>
  </div>
</template>

<script lang="ts">
import { Component, Prop, Vue } from "vue-facing-decorator";
import { AppString, NotificationIface } from "../constants/app";

import { Contact } from "../db/tables/contacts";
import * as databaseUtil from "../db/databaseUtil";

import { logger } from "../utils/logger";
import { PlatformServiceFactory } from "../services/PlatformServiceFactory";
import {
  PlatformService,
  PlatformCapabilities,
} from "../services/PlatformService";
import { contactsToExportJson } from "../libs/util";

/**
 * @vue-component
 * Data Export Section Component
 * Handles database export and seed backup functionality with platform-specific behavior
 */
@Component
export default class DataExportSection extends Vue {
  /**
   * Notification function injected by Vue
   * Used to show success/error messages to the user
   */
  $notify!: (notification: NotificationIface, timeout?: number) => void;

  /**
   * Active DID (Decentralized Identifier) of the user
   * Controls visibility of seed backup option
   * @required
   */
  @Prop({ required: true }) readonly activeDid!: string;

  /**
   * URL for the database export download
   * Created and revoked dynamically during export process
   * Only used in web platform
   */
  downloadUrl = "";

  /**
   * Platform service instance for platform-specific operations
   */
  private platformService: PlatformService =
    PlatformServiceFactory.getInstance();

  /**
   * Platform capabilities for the current platform
   */
  private get platformCapabilities(): PlatformCapabilities {
    return this.platformService.getCapabilities();
  }

  /**
   * Lifecycle hook to clean up resources
   * Revokes object URL when component is unmounted (web platform only)
   */
  beforeUnmount() {
    if (this.downloadUrl && this.platformCapabilities.hasFileDownload) {
      URL.revokeObjectURL(this.downloadUrl);
    }
  }

  /**
   * Exports the database to a JSON file
   * Uses platform-specific methods for saving the exported data
   * Shows success/error notifications to user
   *
   * @throws {Error} If export fails
   * @emits {Notification} Success or error notification
   */
  public async exportDatabase() {
    try {
      let allContacts: Contact[] = [];
      const platformService = PlatformServiceFactory.getInstance();
      const result = await platformService.dbQuery(`SELECT * FROM contacts`);
      if (result) {
        allContacts = databaseUtil.mapQueryResultToValues(
          result,
        ) as unknown as Contact[];
      }
      // if (USE_DEXIE_DB) {
      //   await db.open();
      //   allContacts = await db.contacts.toArray();
      // }

      // Convert contacts to export format
      const exportData = contactsToExportJson(allContacts);
      const jsonStr = JSON.stringify(exportData, null, 2);
      const blob = new Blob([jsonStr], { type: "application/json" });

      const fileName = `${AppString.APP_NAME_NO_SPACES}-backup-contacts.json`;

      if (this.platformCapabilities.hasFileDownload) {
        // Web platform: Use download link
        this.downloadUrl = URL.createObjectURL(blob);
        const downloadAnchor = this.$refs.downloadLink as HTMLAnchorElement;
        downloadAnchor.href = this.downloadUrl;
        downloadAnchor.download = fileName;
        downloadAnchor.click();
        setTimeout(() => URL.revokeObjectURL(this.downloadUrl), 1000);
      } else if (this.platformCapabilities.hasFileSystem) {
        // Native platform: Write to app directory
        await this.platformService.writeAndShareFile(fileName, jsonStr);
      } else {
        throw new Error("This platform does not support file downloads.");
      }

      this.$notify(
        {
          group: "alert",
          type: "success",
          title: "Export Successful",
          text: this.platformCapabilities.hasFileDownload
            ? "See your downloads directory for the backup."
            : "The backup file has been saved.",
        },
        3000,
      );
    } catch (error) {
      logger.error("Export Error:", error);
      this.$notify(
        {
          group: "alert",
          type: "danger",
          title: "Export Error",
          text: "There was an error exporting the data.",
        },
        3000,
      );
    }
  }

  /**
   * Computes class names for the initial download button
   * @returns Object with 'hidden' class when download is in progress (web platform only)
   */
  public computedStartDownloadLinkClassNames() {
    return {
      hidden: this.downloadUrl && this.platformCapabilities.hasFileDownload,
    };
  }

  /**
   * Computes class names for the secondary download link
   * @returns Object with 'hidden' class when no download is available or not on web platform
   */
  public computedDownloadLinkClassNames() {
    return {
      hidden: !this.downloadUrl || !this.platformCapabilities.hasFileDownload,
    };
  }
}
</script>
