<!--
  HelpNotificationsView.vue - Push Notification Help & Testing Component
  
  User support component that provides comprehensive help and testing functionality
  for push notifications. Critical for users experiencing notification issues.
  
  Key Features:
  - Push notification testing with multiple test scenarios
  - Comprehensive troubleshooting guide for notification issues
  - System permission checks for various platforms and browsers
  - Web push subscription management and diagnostics
  - Direct device testing without push server dependency
  
  User Experience Impact:
  - High priority for users having notification issues
  - Primary troubleshooting resource for notification problems
  - Platform-specific guidance for iOS, Android, Mac, Windows
  - Technical diagnostic tools for developers and support
  
  Database Operations:
  - Settings updates for notification preferences via PlatformServiceMixin
  - Simple key-value updates for notification configuration
  - No complex queries or data relationships
  
  Security Considerations:
  - No sensitive data exposure in notifications or logs
  - Safe diagnostic information display
  - Secure push subscription handling
  
  @author Matthew Raymer
-->
<template>
  <QuickNav />

  <!-- CONTENT -->
  <section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
    <!-- Sub View Heading -->
    <div id="SubViewHeading" class="flex gap-4 items-start mb-8">
      <h1 class="grow text-xl text-center font-semibold leading-tight">
        Notification Help
      </h1>

      <!-- Back -->
      <a
        class="order-first text-lg text-center leading-none p-1"
        @click="goBack()"
      >
        <font-awesome icon="chevron-left" class="block text-center w-[1em]" />
      </a>

      <!-- Help button -->
      <router-link
        :to="{ name: 'help' }"
        class="block ms-auto text-sm text-center text-white bg-gradient-to-b from-blue-400 to-blue-700 shadow-[inset_0_-1px_0_0_rgba(0,0,0,0.5)] p-1.5 rounded-full"
      >
        <font-awesome icon="question" class="block text-center w-[1em]" />
      </router-link>
    </div>

    <!-- eslint-disable prettier/prettier -->
    <div>
      <p>Here are ways to test notifications and get them working.</p>

      <h2 class="text-xl font-semibold mt-4">Full Test</h2>
      <div>
        <p>
          If this works then you're all set.
          <button
            :class="primaryTestButtonClass"
            @click="sendTestWebPushMessage(true)"
          >
            Send Yourself a Test Web Push Message (Through Push Server but
            Skipping Client Filter)
          </button>
        </p>
      </div>

      <h2 class="text-xl font-semibold mt-4">Android Users</h2>
      <div>
        <p>
          Note that you may not receive notifications when the app is in the
          background. When you're done working, close the app, and then you'll
          get the reminder notifications.
        </p>
      </div>

      <h2 class="text-xl font-semibold mt-4">
        If this app doesn't support notifications...
        <!-- Note that that exact verbiage shows in a message elsewhere. -->
      </h2>
      <div>
        <p>
          To be notified of interesting updates, install this app on your device
          (as opposed to using it inside the browser app). In Chrome, it may prompt
          you, and you can also look for the "Install" command in the browser
          settings.
        </p>
      </div>

      <h2 class="text-xl font-semibold mt-4">
        If you must enable notifications...
        <!-- Note that that exact verbiage shows in a message elsewhere. -->
      </h2>
      <div>
        <p>
          <button class="text-blue-500" @click="showNotificationChoice()">
            Click here.
          </button>
          <PushNotificationPermission ref="pushNotificationPermission" />
        </p>
      </div>

      <h2 class="text-xl font-semibold mt-4">
        If you're waiting for system initialization...
        <!-- Note that that exact verbiage shows in a message elsewhere. -->
      </h2>
      <div>
        <p>
          ... and it never stops, then there is a problem with the underlying
          service worker or push server mechanism in your browser. Your best bet
          is to follow the "Reinstall" steps below or use a different browser.
        </p>
      </div>

      <h2 class="text-xl font-semibold mt-4">Check App Permissions</h2>
      <div>
        <p>
          In Apple iOS, check "Settings" -> "Notifications", look for the Time
          Safari app (or the browser you're using), and make sure notifications
          are enabled.
        </p>
        <p>
          In Android, hold on to the app icon, then select "App Info", then
          "Notifications" and make sure they're enabled. If it's still a problem
          then go further:
        </p>
        <p>
          If you installed the app with Chrome, make sure there are no other
          tabs with it open. Here are some ways to clear caches that can mess
          things up (and note that this clears out data from the installed app
          -- which is good to do while the app is installed):
        </p>
        <ul>
          <li class="list-disc ml-4">
            Go to Chrome "App Info", then "Storage & Cache" and "Clear Storage".
          </li>
          <li class="list-disc ml-4">
            Go to Chrome "Settings", then "Privacy and Security" and "Clear
            "Clear browsing data", then "Cookies and site data". Make sure the
            "Time Range" at the top shows "All time".
          </li>
        </ul>
        <p>
          On a Mac, go to "Settings" and check "Notifications".
          <img
            src="../assets/help/mac-installed-app-settings.png"
            alt="Mac app settings"
            class="ml-4"
          />
        </p>
      </div>

      <h2 class="text-xl font-semibold mt-4">Check Browser Permissions</h2>
      <div>
        <p>In Apple iOS, check Settings -> Notifications.</p>
        <p>In Android, check Settings -> Notifications.</p>

        You can find more details about compatibility
        <a
          href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API#browser_compatibility"
          class="text-blue-500"
          target="_blank"
        >
          here <font-awesome icon="arrow-up-right-from-square" class="fa-fw" />
        </a>
      </div>

      <h2 class="text-xl font-semibold mt-4">
        Check Operating System (OS) Permissions
      </h2>
      <div class="px-2">
        <div>
          <h3 class="text-lg font-semibold">Mobile Phone - Apple iOS</h3>
          <div>
            Notifications require iOS 16.4 or higher. To check your iOS version,
            go to Settings > General > About > Software Version.
          </div>

          <h3 class="text-lg font-semibold">Mobile Phone - Google Android</h3>
          <div>
            We recommend Chrome. It must be version 42 or higher. Check your
            version under Settings -> About Chrome.
          </div>

          <h3 class="text-lg font-semibold">Desktop - Mac</h3>
          <div>
            <span>
              See "System Settings" -> "Notifications" and make sure it is
              enabled for the browser you're using. Note that these
              notifications require Mac OS 13; see your macOS version under
              Apple -> "About This Mac".
            </span>
          </div>

          <h3 class="text-lg font-semibold">Desktop - Windows</h3>
          In Windows, check "Settings" -> "Notifications".
          <img
            src="../assets/help/windows-system-enable-notifications.png"
            alt="Windows system settings"
            class="ml-4"
          />
        </div>
        <div>
          You can find more details about compatibility
          <a
            href="https://developer.mozilla.org/en-US/docs/Web/API/Push_API#browser_compatibility"
            class="text-blue-500"
            target="_blank"
          >
            here <font-awesome icon="arrow-up-right-from-square" class="fa-fw" />
          </a>
        </div>
      </div>

      <h2 class="text-xl font-semibold mt-4">Reinstall</h2>
      <div>
        <p>
          If all else fails, it's best to start over.
        </p>
        <p>
          Of course, you'll want to back up all your data first -- all seeds as
          well as the contacts & settings -- on the Profile
          <font-awesome icon="circle-user" /> page.
        </p>
        <p>
          Here are instructions to uninstall the app and clear out caches and storage.
          Note that you should first ensure check that the browser tabs with Time Safari are closed.
          (If any are open then that will interfere with your refresh.)
        </p>
        <ul class="ml-4 list-disc">
          <li>
            Clear cache.
            <ul>
              <li>
                In mobile, look for the browser app settings. This is true even
                for an installed app: go to the browser which you used to
                initially visit timesafari.app, because those settings affect
                the app. Look for "Delete browsing data" in the "Settings",
                under "Privacy and Security".
              </li>
              <li>
                In Chrome, go to `chrome://settings/cookies` and "all site data
                and permissions" for timesafari.app; in Firefox, go to
                `about:preferences` and search for "cache" then "Manage Data"
                for timesafari.app. Also manually remove the IndexedDB data if
                the DBs still show.)
              </li>
            </ul>
          </li>
          <li>
            Clear notification permission. (In Chrome, go to
            `chrome://settings/content/notifications`; in Firefox, go to
            `about:preferences` and search for "notifications".)
          </li>
          <li>
            Unregister service worker. (In Chrome, go to
            `chrome://serviceworker-internals/`; in Firefox, go to
            `about:serviceworkers`.)
          </li>
          <li>
            Clear "Cache Storage". (In Chrome, in dev tools under "Application";
            in Firefox, in dev tools under "Storage".)
          </li>
        </ul>
        <p>Then reinstall the app.</p>
      </div>

      <h2 class="text-xl font-semibold mt-4">Tests</h2>
      <button
        :class="testButtonClass"
        @click="showTestNotification()"
      >
        Send Test Notification Directly to Device (Not Through Push Server)
      </button>
      <p>
        If that didn't show a notification on your device, the problem is that
        your browser or your operating system are not allowing notifications
        through. See "Check App Permissions" and "Check Browser Permissions" and
        "Check Operating System (OS) Permissions" above.
      </p>

      <button
        :class="testButtonClass"
        @click="alertWebPushSubscription()"
      >
        Show Web Push Subscription Info
      </button>
      <p>
        If that showed "null" then the notification is not active.
        <button class="text-blue-500" @click="showNotificationChoice()">
          Click here.
        </button>
      </p>

      <button
        :class="testButtonClass"
        @click="sendTestWebPushMessage(true)"
      >
        Send Yourself a Test Web Push Message (Through Push Server but Skipping
        Client Filter)
      </button>
      <p>
        If that didn't show a notification on your device, there is a problem
        getting to the push server. Disable notifications and then enable them
        again.
      </p>

      <button
        :class="testButtonClass"
        @click="sendTestWebPushMessage()"
      >
        Send Yourself a Test Web Push Message (Through Push Server and Client
        Filter)
      </button>
      <p>
        If you don't see a message, it could be that there is nothing new for
        you to see. If the previous test worked, then things should work fine.
        If you notice a full 24 hours where you get no notification and you know
        that there are new items that should show, gather as many details as
        possible and go to the bottom of
        <router-link to="help" class="text-blue-500"> this page </router-link>
        for ways to contact us.
      </p>
    </div>
    <!-- eslint-enable -->
  </section>
</template>
<script lang="ts">
import { Component, Vue } from "vue-facing-decorator";

import QuickNav from "../components/QuickNav.vue";
import { NotificationIface } from "../constants/app";
import { DIRECT_PUSH_TITLE, sendTestThroughPushServer } from "../libs/util";
import PushNotificationPermission from "../components/PushNotificationPermission.vue";
import { PlatformServiceMixin } from "../utils/PlatformServiceMixin";
import { createNotifyHelpers, TIMEOUTS } from "../utils/notify";
import {
  NOTIFY_PUSH_NOT_SUBSCRIBED,
  NOTIFY_TEST_WEB_PUSH_SUCCESS,
  NOTIFY_TEST_WEB_PUSH_ERROR,
  NOTIFY_TEST_NOTIFICATION_SUCCESS,
  NOTIFY_TEST_NOTIFICATION_ERROR,
} from "../constants/notifications";
import { Router } from "vue-router";
import { logger } from "../utils/logger";

/**
 * HelpNotificationsView Component
 *
 * User support component that provides comprehensive help and testing functionality
 * for push notifications. Critical for users experiencing notification issues.
 *
 * Key features:
 * - Push notification testing with multiple test scenarios
 * - Comprehensive troubleshooting guide for notification issues
 * - System permission checks for various platforms and browsers
 * - Web push subscription management and diagnostics
 * - Direct device testing without push server dependency
 *
 * User Experience Impact:
 * - High priority for users having notification issues
 * - Primary troubleshooting resource for notification problems
 * - Platform-specific guidance for iOS, Android, Mac, Windows
 * - Technical diagnostic tools for developers and support
 *
 * Database Operations:
 * - Settings updates for notification preferences via PlatformServiceMixin
 * - Simple key-value updates for notification configuration
 * - No complex queries or data relationships
 *
 * Security Features:
 * - No sensitive data exposure in notifications or logs
 * - Safe diagnostic information display
 * - Secure push subscription handling
 * - Proper error handling without data leakage
 *
 * @author Matthew Raymer
 */
@Component({
  components: { PushNotificationPermission, QuickNav },
  mixins: [PlatformServiceMixin],
})
export default class HelpNotificationsView extends Vue {
  $notify!: (notification: NotificationIface, timeout?: number) => void;
  $router!: Router;
  subscriptionJSON?: PushSubscriptionJSON;
  notifyingReminder = false;
  notifyingReminderMessage = "";
  notifyingReminderTime = "";

  // Notification helper system
  notify!: ReturnType<typeof createNotifyHelpers>;

  /**
   * Computed property for consistent button styling
   * Used for all test buttons in the notification help interface
   */
  get buttonClass(): string {
    return "block w-full text-center text-md 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-1.5 py-2 rounded-md";
  }

  /**
   * Computed property for test button styling with margins
   * Used for test buttons in the Tests section
   */
  get testButtonClass(): string {
    return this.buttonClass + " mt-4 mb-2";
  }

  /**
   * Computed property for primary test button styling
   * Used for the main test button with bottom margin
   */
  get primaryTestButtonClass(): string {
    return this.buttonClass + " mb-2";
  }

  /**
   * Vue mounted lifecycle hook
   *
   * Initializes the component by setting up push subscription information.
   * Retrieves the current push subscription from the service worker and stores
   * it for display and testing purposes.
   *
   * Handles errors gracefully with proper logging without exposing sensitive data.
   */
  async mounted() {
    // Initialize notification helpers
    this.notify = createNotifyHelpers(this.$notify);

    try {
      const registration = await navigator.serviceWorker?.ready;
      const fullSub = await registration?.pushManager.getSubscription();
      this.subscriptionJSON = fullSub?.toJSON();
    } catch (error) {
      logger.error("Mount error:", error);
    }
  }

  /**
   * Navigates back to the previous page
   * Provides consistent navigation behavior for the back button
   */
  goBack(): void {
    this.$router.back();
  }

  /**
   * Displays web push subscription information
   *
   * Shows the current push subscription details to the user for diagnostic purposes.
   * Useful for troubleshooting push notification issues and verifying subscription status.
   */
  alertWebPushSubscription() {
    alert(JSON.stringify(this.subscriptionJSON));
  }

  /**
   * Sends test web push message through push server
   *
   * Sends a test notification through the push server to verify the complete
   * notification pipeline. Can skip client-side filtering for testing purposes.
   *
   * @param skipFilter - Whether to skip client-side message filtering
   */
  async sendTestWebPushMessage(skipFilter: boolean = false) {
    if (!this.subscriptionJSON) {
      this.notify.error(NOTIFY_PUSH_NOT_SUBSCRIBED.message, TIMEOUTS.STANDARD);
      return;
    }

    try {
      await sendTestThroughPushServer(this.subscriptionJSON, skipFilter);

      this.notify.success(
        this.getTestWebPushSuccessMessage(skipFilter),
        TIMEOUTS.STANDARD,
      );
    } catch (error) {
      logger.error("Got an error sending test notification:", error);
      this.notify.error(NOTIFY_TEST_WEB_PUSH_ERROR.message, TIMEOUTS.STANDARD);
    }
  }

  /**
   * Shows test notification directly to device
   *
   * Displays a test notification directly through the service worker without
   * using the push server. Useful for testing local notification capabilities.
   */
  showTestNotification() {
    const TEST_NOTIFICATION_TITLE = "It Worked";
    navigator.serviceWorker?.ready
      .then((registration) => {
        return registration.showNotification(TEST_NOTIFICATION_TITLE, {
          body: "This is your test notification.",
        });
      })
      .then(() => {
        this.notify.success(
          this.getTestNotificationSuccessMessage(TEST_NOTIFICATION_TITLE),
          TIMEOUTS.STANDARD,
        );
      })
      .catch((error) => {
        logger.error("Got a notification error:", error);
        this.notify.error(
          NOTIFY_TEST_NOTIFICATION_ERROR.message,
          TIMEOUTS.STANDARD,
        );
      });
  }

  /**
   * Shows notification permission choice dialog
   *
   * Opens the notification permission dialog to allow users to enable
   * notifications. Updates notification settings upon successful permission grant.
   */
  showNotificationChoice() {
    (this.$refs.pushNotificationPermission as PushNotificationPermission).open(
      DIRECT_PUSH_TITLE,
      async (success: boolean, timeText: string, message?: string) => {
        if (success) {
          await this.$updateSettings({
            notifyingReminderMessage: message,
            notifyingReminderTime: timeText,
          });
          this.notifyingReminder = true;
          this.notifyingReminderMessage = message || "";
          this.notifyingReminderTime = timeText;
        }
      },
    );
  }

  /**
   * Generates test web push success message
   *
   * Creates a dynamic success message based on whether client filtering is skipped.
   *
   * @param skipFilter - Whether client-side message filtering was skipped
   * @returns Formatted success message string
   */
  private getTestWebPushSuccessMessage(skipFilter: boolean): string {
    return (
      NOTIFY_TEST_WEB_PUSH_SUCCESS.message +
      (skipFilter ? "." : " if there are new items in your feed.")
    );
  }

  /**
   * Generates test notification success message
   *
   * Creates a dynamic success message with the notification title inserted.
   *
   * @param title - The title of the test notification
   * @returns Formatted success message string
   */
  private getTestNotificationSuccessMessage(title: string): string {
    return NOTIFY_TEST_NOTIFICATION_SUCCESS.message.replace("{title}", title);
  }
}
</script>
