<template>
  <router-view />

  <!-- Messages in the upper-right - https://github.com/emmanuelsw/notiwind -->
  <NotificationGroup group="alert">
    <div
      class="fixed top-[calc(env(safe-area-inset-top)+1rem)] right-4 left-4 sm:left-auto sm:w-full sm:max-w-sm flex flex-col items-start justify-end"
    >
      <Notification
        v-slot="{ notifications, close }"
        enter="transform ease-out duration-300 transition"
        enter-from="translate-y-2 opacity-0 sm:translate-y-0 sm:translate-x-4"
        enter-to="translate-y-0 opacity-100 sm:translate-x-0"
        leave="transition ease-in duration-500"
        leave-from="opacity-100"
        leave-to="opacity-0"
        move="transition duration-500"
        move-delay="delay-300"
      >
        <div
          v-for="notification in notifications"
          :key="notification.id"
          class="w-full"
          role="alert"
        >
          <div
            v-if="notification.type === 'toast'"
            class="w-full max-w-sm mx-auto mb-3 overflow-hidden bg-slate-900/90 text-white rounded-lg shadow-md"
          >
            <div class="w-full px-4 py-3">
              <span class="font-semibold">{{ notification.title }}</span>
              <p class="text-sm">{{ notification.text }}</p>
            </div>
          </div>

          <div
            v-if="notification.type === 'info'"
            class="flex w-full max-w-sm mx-auto mb-3 overflow-hidden bg-slate-100 rounded-lg shadow-md"
          >
            <div
              class="flex items-center justify-center w-12 bg-slate-600 text-slate-100"
            >
              <font-awesome
                icon="circle-info"
                class="fa-fw fa-xl"
              ></font-awesome>
            </div>

            <div class="relative w-full pl-4 pr-8 py-2 text-slate-900">
              <span class="font-semibold">{{ notification.title }}</span>
              <p class="text-sm">{{ truncateLongWords(notification.text) }}</p>

              <button
                class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-slate-200 text-slate-600"
                @click="close(notification.id)"
              >
                <font-awesome icon="xmark" class="fa-fw"></font-awesome>
              </button>
            </div>
          </div>

          <div
            v-if="notification.type === 'success'"
            class="flex w-full max-w-sm mx-auto mb-3 overflow-hidden bg-emerald-100 rounded-lg shadow-md"
          >
            <div
              class="flex items-center justify-center w-12 bg-emerald-600 text-emerald-100"
            >
              <font-awesome
                icon="circle-info"
                class="fa-fw fa-xl"
              ></font-awesome>
            </div>

            <div class="relative w-full pl-4 pr-8 py-2 text-emerald-900">
              <span class="font-semibold">{{ notification.title }}</span>
              <p class="text-sm">{{ truncateLongWords(notification.text) }}</p>

              <button
                class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-emerald-200 text-emerald-600"
                @click="close(notification.id)"
              >
                <font-awesome icon="xmark" class="fa-fw"></font-awesome>
              </button>
            </div>
          </div>

          <div
            v-if="notification.type === 'warning'"
            class="flex w-full max-w-sm mx-auto mb-3 overflow-hidden bg-amber-100 rounded-lg shadow-md"
          >
            <div
              class="flex items-center justify-center w-12 bg-amber-600 text-amber-100"
            >
              <font-awesome
                icon="triangle-exclamation"
                class="fa-fw fa-xl"
              ></font-awesome>
            </div>

            <div class="relative w-full pl-4 pr-8 py-2 text-amber-900">
              <span class="font-semibold">{{ notification.title }}</span>
              <p class="text-sm">{{ truncateLongWords(notification.text) }}</p>

              <button
                class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-amber-200 text-amber-600"
                @click="close(notification.id)"
              >
                <font-awesome icon="xmark" class="fa-fw"></font-awesome>
              </button>
            </div>
          </div>

          <div
            v-if="notification.type === 'danger'"
            class="flex w-full max-w-sm mx-auto mb-3 overflow-hidden bg-rose-100 rounded-lg shadow-md"
          >
            <div
              class="flex items-center justify-center w-12 bg-rose-600 text-rose-100"
            >
              <font-awesome
                icon="triangle-exclamation"
                class="fa-fw fa-xl"
              ></font-awesome>
            </div>

            <div class="relative w-full pl-4 pr-8 py-2 text-rose-900">
              <span class="font-semibold">{{ notification.title }}</span>
              <p class="text-sm">{{ truncateLongWords(notification.text) }}</p>

              <button
                class="absolute top-2 right-2 px-0.5 py-0 rounded-full bg-rose-200 text-rose-600"
                @click="close(notification.id)"
              >
                <font-awesome icon="xmark" class="fa-fw"></font-awesome>
              </button>
            </div>
          </div>
        </div>
      </Notification>
    </div>
  </NotificationGroup>

  <!--
    This "group" of "modal" is the prompt for an answer.
    Set "type" as follows: "confirm" for yes/no, and "notification" ones:
      "-permission", "-mute", "-off"
  -->
  <NotificationGroup group="modal">
    <div class="fixed z-[100] top-[env(safe-area-inset-top)] inset-x-0 w-full">
      <Notification
        v-slot="{ notifications, close }"
        enter="transform ease-out duration-300 transition"
        enter-from="translate-y-2 opacity-0 sm:translate-y-4"
        enter-to="translate-y-0 opacity-100 sm:translate-y-0"
        leave="transition ease-in duration-500"
        leave-from="opacity-100"
        leave-to="opacity-0"
        move="transition duration-500"
        move-delay="delay-300"
      >
        <!-- see NotificationIface in constants/app.ts -->
        <div
          v-for="notification in notifications"
          :key="notification.id"
          class="w-full"
          role="alert"
        >
          <!--
            Type of "confirm" will post a message.
            With onYes function, show a "Yes" button to call that function.
            With onNo function, show a "No" button to call that function,
              and pass it state of "askAgain" field shown if you set promptToStopAsking.
          -->
          <div
            v-if="notification.type === 'confirm'"
            class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
          >
            <div
              class="flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg"
            >
              <div class="w-full px-6 py-6 text-slate-900 text-center">
                <span class="font-semibold text-lg">
                  {{ notification.title }}
                </span>
                <p class="text-sm mb-2">{{ notification.text }}</p>

                <button
                  v-if="notification.onYes"
                  class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
                  @click="
                    notification.onYes();
                    close(notification.id);
                  "
                >
                  Yes{{
                    notification.yesText ? ", " + notification.yesText : ""
                  }}
                </button>

                <button
                  v-if="notification.onNo"
                  class="block w-full text-center text-md font-bold uppercase bg-yellow-600 text-white px-2 py-2 rounded-md mb-2"
                  @click="
                    notification.onNo(stopAsking);
                    close(notification.id);
                    stopAsking = false; // reset value
                  "
                >
                  No{{ notification.noText ? ", " + notification.noText : "" }}
                </button>

                <label
                  v-if="notification.promptToStopAsking && notification.onNo"
                  for="toggleStopAsking"
                  class="flex items-center justify-between cursor-pointer my-4"
                  @click="stopAsking = !stopAsking"
                >
                  <!-- label -->
                  <span class="ml-2">... and do not ask again.</span>
                  <!-- toggle -->
                  <div class="relative ml-2">
                    <!-- input -->
                    <input
                      v-model="stopAsking"
                      type="checkbox"
                      name="stopAsking"
                      class="sr-only"
                    />
                    <!-- line -->
                    <div class="block bg-slate-500 w-14 h-8 rounded-full"></div>
                    <!-- dot -->
                    <div
                      class="dot absolute left-1 top-1 bg-slate-400 w-6 h-6 rounded-full transition"
                    ></div>
                  </div>
                </label>

                <button
                  class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
                  @click="
                    notification.onCancel
                      ? notification.onCancel(stopAsking)
                      : null;
                    close(notification.id);
                    stopAsking = false; // reset value for next time they open this modal
                  "
                >
                  {{ notification.onYes ? "Cancel" : "Close" }}
                </button>
              </div>
            </div>
          </div>

          <div
            v-if="notification.type === 'notification-mute'"
            class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
          >
            <div
              class="flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg"
            >
              <div class="w-full px-6 py-6 text-slate-900 text-center">
                <p class="text-lg mb-4">Mute app notifications:</p>

                <button
                  class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
                >
                  For 1 Day
                </button>
                <button
                  class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
                >
                  For 2 Days
                </button>
                <button
                  class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
                >
                  For 1 Week
                </button>
                <button
                  class="block w-full text-center text-md font-bold uppercase bg-blue-600 text-white px-2 py-2 rounded-md mb-2"
                >
                  Until I turn it back on
                </button>
                <button
                  class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
                  @click="close(notification.id)"
                >
                  Cancel
                </button>
              </div>
            </div>
          </div>

          <div
            v-if="notification.type === 'notification-off'"
            class="absolute inset-0 h-screen flex flex-col items-center justify-center bg-slate-900/50"
          >
            <div
              class="flex w-11/12 max-w-sm mx-auto mb-3 overflow-hidden bg-white rounded-lg shadow-lg"
            >
              <div class="w-full px-6 py-6 text-slate-900 text-center">
                <p class="text-lg mb-4">
                  Would you like to <b>turn off</b> this notification?
                </p>

                <button
                  class="block w-full text-center text-md font-bold uppercase bg-rose-600 text-white px-2 py-2 rounded-md mb-2"
                  @click="
                    close(notification.id);
                    turnOffNotifications(notification);
                  "
                >
                  Turn Off Notification
                </button>
                <button
                  class="block w-full text-center text-md font-bold uppercase bg-slate-600 text-white px-2 py-2 rounded-md"
                  @click="close(notification.id)"
                >
                  Leave it On
                </button>
              </div>
            </div>
          </div>
        </div>
      </Notification>
    </div>
  </NotificationGroup>
</template>

<script lang="ts">
import { Vue, Component } from "vue-facing-decorator";
import { logConsoleAndDb, retrieveSettingsForActiveAccount } from "./db/index";
import { NotificationIface } from "./constants/app";
import { logger } from "./utils/logger";

interface Settings {
  notifyingNewActivityTime?: string;
  notifyingReminderTime?: string;
}

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

  stopAsking = false;

  // created() {
  //   logger.log(
  //     "Component created: Reactivity set up.",
  //     window.location.pathname,
  //   );
  // }

  // beforeCreate() {
  //   logger.log("Component beforeCreate: Instance initialized.");
  // }

  // beforeMount() {
  //   logger.log("Component beforeMount: Template is about to be rendered.");
  // }

  // mounted() {
  //   logger.log("Component mounted: Template is now rendered.");
  // }

  // beforeUpdate() {
  //   logger.log("Component beforeUpdate: DOM is about to be updated.");
  // }

  // updated() {
  //   logger.log("Component updated: DOM has been updated.");
  // }

  // beforeUnmount() {
  //   logger.log("Component beforeUnmount: Cleaning up before removal.");
  // }

  // unmounted() {
  //   logger.log("Component unmounted: Component removed from the DOM.");
  // }

  truncateLongWords(sentence: string) {
    return sentence
      .split(" ")
      .map((word) => (word.length > 30 ? word.slice(0, 30) + "..." : word))
      .join(" ");
  }

  async turnOffNotifications(
    notification: NotificationIface,
  ): Promise<boolean> {
    logger.log("Starting turnOffNotifications...");
    let subscription: PushSubscriptionJSON | null = null;
    let allGoingOff = false;

    try {
      logger.log("Retrieving settings for the active account...");
      const settings: Settings = await retrieveSettingsForActiveAccount();
      logger.log("Retrieved settings:", settings);

      const notifyingNewActivity = !!settings?.notifyingNewActivityTime;
      const notifyingReminder = !!settings?.notifyingReminderTime;

      if (!notifyingNewActivity || !notifyingReminder) {
        allGoingOff = true;
        logger.log("Both notifications are being turned off.");
      }

      logger.log("Checking service worker readiness...");
      await navigator.serviceWorker?.ready
        .then((registration) => {
          logger.log("Service worker is ready. Fetching subscription...");
          return registration.pushManager.getSubscription();
        })
        .then(async (subscript: PushSubscription | null) => {
          if (subscript) {
            subscription = subscript.toJSON();
            logger.log("PushSubscription retrieved:", subscription);

            if (allGoingOff) {
              logger.log("Unsubscribing from push notifications...");
              await subscript.unsubscribe();
              logger.log("Successfully unsubscribed.");
            }
          } else {
            logConsoleAndDb("Subscription object is not available.");
            logger.log("No subscription found.");
          }
        })
        .catch((error) => {
          logConsoleAndDb(
            "Push provider server communication failed: " +
              JSON.stringify(error),
            true,
          );
          logger.error("Error during subscription fetch:", error);
        });

      if (!subscription) {
        logger.log("No subscription available. Notifying user...");
        this.$notify(
          {
            group: "alert",
            type: "info",
            title: "Finished",
            text: "Notifications are off.",
          },
          5000,
        );
        logger.log("Exiting as there is no subscription to process.");
        return true;
      }

      const serverSubscription = {
        ...subscription,
      };
      if (!allGoingOff) {
        serverSubscription["notifyType"] = notification.title;
        logger.log(
          `Server subscription updated with notifyType: ${notification.title}`,
        );
      }

      logger.log("Sending unsubscribe request to the server...");
      const pushServerSuccess = await fetch("/web-push/unsubscribe", {
        method: "POST",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(serverSubscription),
      })
        .then(async (response) => {
          if (!response.ok) {
            const errorBody = await response.text();
            logConsoleAndDb(
              `Push server failed: ${response.status} ${errorBody}`,
              true,
            );
            logger.error("Push server error response:", errorBody);
          }
          logger.log(`Server response status: ${response.status}`);
          return response.ok;
        })
        .catch((error) => {
          logConsoleAndDb(
            "Push server communication failed: " + JSON.stringify(error),
            true,
          );
          logger.error("Error during server communication:", error);
          return false;
        });

      const message = pushServerSuccess
        ? "Notification is off."
        : "Notification is still on. Try to turn it off again.";
      logger.log("Server response processed. Message:", message);

      this.$notify(
        {
          group: "alert",
          type: "info",
          title: "Finished",
          text: message,
        },
        5000,
      );

      if (notification.callback) {
        logger.log("Executing notification callback...");
        notification.callback(pushServerSuccess);
      }

      logger.log(
        "Completed turnOffNotifications with success:",
        pushServerSuccess,
      );
      return pushServerSuccess;
    } catch (error) {
      logConsoleAndDb(
        "Error turning off notifications: " + JSON.stringify(error),
        true,
      );
      logger.error("Critical error in turnOffNotifications:", error);

      this.$notify(
        {
          group: "alert",
          type: "error",
          title: "Error",
          text: "Failed to turn off notifications. Please try again.",
        },
        5000,
      );

      return false;
    }
  }
}
</script>

<style>
#Content {
  padding-left: 1.5rem;
  padding-right: 1.5rem;
  padding-top: calc(env(safe-area-inset-top) + 1.5rem);
  padding-bottom: calc(env(safe-area-inset-bottom) + 1.5rem);
}

#QuickNav ~ #Content {
  padding-bottom: calc(env(safe-area-inset-bottom) + 6rem);
}
</style>