"use client";

import { useEffect, useState } from "react";
import { Bell, BellOff, Check, Loader2 } from "lucide-react";
import { getReadableTextColor } from "@/lib/color-contrast";

/*
  "Avise no meu celular quando a loja responder."

  Sem isto, o cliente que manda uma duvida a noite so descobre a resposta se
  lembrar de voltar ao portal. O aviso e por aparelho e so vale para este
  pedido e os outros dele — nao vira lista de promocao.

  No iPhone so funciona com o site na tela inicial; a faixa diz isso em vez de
  pedir permissao e falhar calada.
*/

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((caractere) => caractere.charCodeAt(0)));
}

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

export default function AtivarAvisosDoCliente({ slug, primaryColor }: { slug: string; primaryColor: string }) {
  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(() => {
    void (async () => {
      if (!chavePublica) return setEstado("indisponivel");
      if (!("serviceWorker" in navigator) || !("PushManager" in window)) {
        const ehApple = /iPad|iPhone|iPod/.test(navigator.userAgent);
        return setEstado(ehApple ? "precisa_instalar" : "indisponivel");
      }
      if (Notification.permission === "denied") return setEstado("negado");

      try {
        const registro = await navigator.serviceWorker.register("/sw.js");
        const atual = await registro.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 registro = await navigator.serviceWorker.ready;
      const assinatura = await registro.pushManager.subscribe({
        userVisibleOnly: true,
        applicationServerKey: base64ParaBytes(chavePublica!),
      });
      const resposta = await fetch("/api/client-portal/push", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({ slug, assinatura: assinatura.toJSON(), user_agent: navigator.userAgent }),
      });
      if (!resposta.ok) {
        throw new Error((await resposta.json().catch(() => null))?.error || "Não consegui ativar.");
      }
      setEstado("ligado");
    } catch (falha) {
      setErro(falha instanceof Error ? falha.message : "Não consegui ativar os avisos.");
    } finally {
      setOcupado(false);
    }
  }

  async function desligar() {
    setOcupado(true);
    try {
      const registro = await navigator.serviceWorker.ready;
      const atual = await registro.pushManager.getSubscription();
      if (atual) {
        await fetch(
          `/api/client-portal/push?slug=${encodeURIComponent(slug)}&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;

  if (estado === "precisa_instalar") {
    return (
      <span className="inline-flex items-center gap-1.5 text-[11.5px] text-zinc-500">
        <Bell className="h-3.5 w-3.5" />
        Para avisar no iPhone, adicione esta loja à Tela de Início.
      </span>
    );
  }

  if (estado === "negado") {
    return (
      <span className="inline-flex items-center gap-1.5 text-[11.5px] text-zinc-500">
        <BellOff className="h-3.5 w-3.5" />
        Avisos bloqueados neste aparelho.
      </span>
    );
  }

  if (estado === "ligado") {
    return (
      <button
        type="button"
        onClick={() => void desligar()}
        disabled={ocupado}
        className="inline-flex h-8 items-center gap-1.5 rounded-full border border-emerald-200 bg-emerald-50 px-3 text-[11.5px] font-semibold text-emerald-700"
      >
        <Check className="h-3.5 w-3.5" />
        Avisos ligados
      </button>
    );
  }

  return (
    <div className="flex flex-col items-end gap-1">
      <button
        type="button"
        onClick={() => void ligar()}
        disabled={ocupado}
        className="inline-flex h-8 items-center gap-1.5 rounded-full px-3 text-[11.5px] font-semibold disabled:opacity-60"
        style={{ backgroundColor: primaryColor, color: getReadableTextColor(primaryColor) }}
      >
        {ocupado ? <Loader2 className="h-3.5 w-3.5 animate-spin" /> : <Bell className="h-3.5 w-3.5" />}
        Avisar no meu celular
      </button>
      {erro ? <span className="text-[11px] text-rose-600">{erro}</span> : null}
    </div>
  );
}
