import {
  json,
  type LoaderFunctionArgs,
  type MetaFunction,
} from "@remix-run/node"
import { useLoaderData } from "@remix-run/react"
import React, { Suspense, useEffect, useState } from "react"
import coerceSemver from "semver/functions/coerce"
import versionAtLeast from "semver/functions/gte"
import UAParser from "ua-parser-js"
import { usePush } from "remix-pwa-monorepo/packages/push/client/hook"

export const meta: MetaFunction = () => {
  return [
    { title: "Tack Up Now!" },
    { name: "description", content: "Get equinelive notifications" },
  ]
}

export const loader = async ({ request }: LoaderFunctionArgs) => {
  const userAgent = request.headers.get("user-agent")
  const os = new UAParser(userAgent ?? "").getOS()
  const isSupported =
    os.name !== "iOS" ||
    versionAtLeast(coerceSemver(os.version) ?? "0.0.0", "16.4.0")

  return json({ isSupported })
}

export default function Index() {
  const { isSupported } = useLoaderData<typeof loader>()

  return (
    <div style={{ fontFamily: "system-ui, sans-serif", lineHeight: "1.8" }}>
      <Suspense>
        <LandingMessage isSupported={isSupported} />
      </Suspense>
    </div>
  )
}

function LandingMessage({ isSupported }: { isSupported: boolean }) {
  const isClient = typeof window !== "undefined"
  const notificationsEnabled =
    isClient &&
    "Notification" in window &&
    window.Notification.permission === "granted"

  const isRunningPWA =
    isClient &&
    (("standalone" in navigator && (navigator.standalone as boolean)) ||
      matchMedia("(dislay-mode: standalone)").matches)

  const [rendered, setRendered] = useState(false)
  const [isInstalled, setIsInstalled] = useState(notificationsEnabled)

  useEffect(() => {
    setRendered(true)
  }, [])

  return !isClient || !rendered ? (
    <div>Loading</div>
  ) : isInstalled ? (
    <div>Your Notifications</div>
  ) : isRunningPWA && !notificationsEnabled ? (
    <EnableButton onSubscribe={() => setIsInstalled(true)} />
  ) : isSupported ? (
    <div>Install Tack Up Now!</div>
  ) : (
    <div>{"Sorry, your device doesn't support Tack Up Now! :("}</div>
  )
}

function EnableButton({ onSubscribe }: { onSubscribe: () => void }) {
  const { subscribeToPush, requestPermission, canSendPush } = usePush()

  function subscribe() {
    console.log("Hey the thing was clicked wow")
    requestPermission()
  }

  useEffect(() => {
    if (!canSendPush) return

    subscribeToPush(
      urlB64ToUint8Array(applicationServerPublicKey) as any,
      (subscription) => {
        fetch("/api/subscribe", {
          method: "POST",
          body: JSON.stringify(subscription),
        })
        onSubscribe()
      },
      (error) => {
        const errorDiv = document.createElement("div")
        errorDiv.innerText = "Error thingy" + JSON.stringify(error)
        document.appendChild(errorDiv)
      }
    )
  }, [canSendPush])

  return <button onClick={subscribe}>Enable notifications</button>
}

const applicationServerPublicKey =
  "BDTbzdtzJxwV0sscdsXla-GKvlcxqQr7edEfkX8-papwvvV1UVc3IMyRacl1BbgTi31nWPji2wKCZkjf1l5iX7Y"

function urlB64ToUint8Array(base64String: string) {
  const padding = "=".repeat((4 - (base64String.length % 4)) % 4)
  const base64 = (base64String + padding).replace(/\-/g, "+").replace(/_/g, "/")

  const rawData = window.atob(base64)
  const outputArray = new Uint8Array(rawData.length)

  for (let i = 0; i < rawData.length; ++i) {
    outputArray[i] = rawData.charCodeAt(i)
  }
  return outputArray
}
