"use client";

import { useEffect, useState } from "react";
import { Bell, BellOff, Loader2 } from "lucide-react";

/**
 * Ativar avisos neste aparelho.
 *
 * A permissao e por aparelho, nao por conta: a pessoa pode querer receber no
 * celular e nao no computador do balcao, que fica ligado o dia todo.
 *
 * No iPhone a notificacao so funciona com o sistema instalado na tela
 * inicial. Em vez de pedir permissao e falhar em silencio, o botao explica o
 * que falta — pedido negado nao volta a ser oferecido pelo navegador.
 */

function base64ParaBytes(base64: string) {
  const preenchido = (base64 + "=".repeat((4 - (base64.length % 4)) % 4))
    .replace(/-/g, "+")
    .replace(/_/g, "/");
  const cru = atob(preenchido);
  return Uint8Array.from([...cru].map((c) => c.charCodeAt(0)));
}

type Estado = "verificando" | "indisponivel" | "precisa_instalar" | "desligado" | "ligado" | "negado";

export default function Avisos() {
  const [estado, setEstado] = useState<Estado>("verificando");
  const [ocupado, setOcupado] = useState(false);
  const [erro, setErro] = useState<string | null>(null);

  const chavePublica = process.env.NEXT_PUBLIC_VAPID_PUBLIC_KEY;

  useEffect(() => {
    (async () => {
      if (!chavePublica) return setEstado("indisponivel");
      if (typeof window === "undefined") return;
      if (!("serviceWorker" in navigator) || !("PushManager" in window)) {
        /* iPhone fora da tela inicial nao expoe PushManager. E o caso mais
           comum de "nao aparece o botao" e vale explicar. */
        const ehApple = /iPad|iPhone|iPod/.test(navigator.userAgent);
        return setEstado(ehApple ? "precisa_instalar" : "indisponivel");
      }
      if (Notification.permission === "denied") return setEstado("negado");

      try {
        const reg = await navigator.serviceWorker.register("/sw.js");
        const atual = await reg.pushManager.getSubscription();
        setEstado(atual ? "ligado" : "desligado");
      } catch {
        setEstado("indisponivel");
      }
    })();
  }, [chavePublica]);

  async function ligar() {
    setOcupado(true);
    setErro(null);
    try {
      const permissao = await Notification.requestPermission();
      if (permissao !== "granted") {
        setEstado(permissao === "denied" ? "negado" : "desligado");
        return;
      }
      const reg = await navigator.serviceWorker.ready;
      const assinatura = await reg.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: base64ParaBytes(chavePublica!),
      });
      const r = await fetch("/api/agenda/push/subscrever", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ assinatura: assinatura.toJSON(), user_agent: navigator.userAgent }),
      });
      if (!r.ok) throw new Error((await r.json().catch(() => null))?.error || "Falha ao ativar.");
      setEstado("ligado");
    } catch (e) {
      setErro(e instanceof Error ? e.message : "Não consegui ativar os avisos.");
    } finally {
      setOcupado(false);
    }
  }

  async function desligar() {
    setOcupado(true);
    try {
      const reg = await navigator.serviceWorker.ready;
      const atual = await reg.pushManager.getSubscription();
      if (atual) {
        await fetch(`/api/agenda/push/subscrever?endpoint=${encodeURIComponent(atual.endpoint)}`, {
          method: "DELETE",
        });
        await atual.unsubscribe();
      }
      setEstado("desligado");
    } catch {
      setErro("Não consegui desligar agora.");
    } finally {
      setOcupado(false);
    }
  }

  if (estado === "verificando" || estado === "indisponivel") return null;

  const caixa =
    "flex flex-wrap items-center gap-2 rounded-xl border border-[var(--ks-color-border-subtle)] bg-[var(--ks-color-bg-elevated)] px-3 py-2.5 text-xs";

  if (estado === "precisa_instalar") {
    return (
      <div className={caixa}>
        <Bell className="h-4 w-4 text-[var(--ks-color-text-muted)]" />
        <span className="text-[var(--ks-color-text-muted)]">
          Para receber avisos no iPhone, toque em Compartilhar e escolha{" "}
          <strong className="text-[var(--ks-color-text-primary)]">Adicionar à Tela de Início</strong>.
        </span>
      </div>
    );
  }

  if (estado === "negado") {
    return (
      <div className={caixa}>
        <BellOff className="h-4 w-4 text-[var(--ks-color-text-muted)]" />
        <span className="text-[var(--ks-color-text-muted)]">
          Os avisos foram bloqueados neste aparelho. Libere nas configurações do navegador para este site.
        </span>
      </div>
    );
  }

  return (
    <div className={caixa}>
      {estado === "ligado" ? (
        <>
          <Bell className="h-4 w-4 text-emerald-500" />
          <span className="font-semibold text-[var(--ks-color-text-primary)]">
            Avisos ligados neste aparelho
          </span>
          <button
            type="button"
            onClick={desligar}
            disabled={ocupado}
            className="ml-auto min-h-[36px] rounded-lg px-3 font-bold text-[var(--ks-color-text-muted)] hover:bg-[var(--ks-color-bg-soft)] disabled:opacity-50"
          >
            Desligar
          </button>
        </>
      ) : (
        <>
          <Bell className="h-4 w-4 text-[var(--ks-color-text-muted)]" />
          <span className="text-[var(--ks-color-text-muted)]">
            Receba os prazos do dia mesmo com o sistema fechado.
          </span>
          <button
            type="button"
            onClick={ligar}
            disabled={ocupado}
            className="ml-auto flex min-h-[36px] items-center gap-1.5 rounded-lg bg-[var(--ks-color-primary)] px-3 font-bold text-white hover:opacity-90 disabled:opacity-50"
          >
            {ocupado && <Loader2 className="h-3.5 w-3.5 animate-spin" />}
            Ativar avisos
          </button>
        </>
      )}
      {erro && <span className="w-full text-rose-600 dark:text-rose-400">{erro}</span>}
    </div>
  );
}
