"use client";

import { motion } from "framer-motion";
import Image from "next/image";
import Link from "next/link";
import { useRouter, useSearchParams } from "next/navigation";
import { ArrowRight, Loader2, LockKeyhole, Mail } from "lucide-react";
import { useEffect, useMemo, useState } from "react";
import { getSupabaseClient } from "@/lib/supabase";
import { getAccessibleAccent, getReadableTextColor } from "@/lib/color-contrast";

function hexToRgba(hex: string, alpha: number) {
  const normalized = String(hex || "").trim().replace("#", "");
  const safe = normalized.length === 3
    ? normalized
        .split("")
        .map((char) => `${char}${char}`)
        .join("")
    : normalized;
  if (!/^[0-9a-fA-F]{6}$/.test(safe)) return `rgba(68, 37, 167, ${alpha})`;
  const int = parseInt(safe, 16);
  const r = (int >> 16) & 255;
  const g = (int >> 8) & 255;
  const b = int & 255;
  return `rgba(${r}, ${g}, ${b}, ${alpha})`;
}

function mapResetError(error?: string | null, errorCode?: string | null, description?: string | null) {
  const haystack = `${error ?? ""} ${errorCode ?? ""} ${description ?? ""}`.toLowerCase();

  if (haystack.includes("pkce code verifier") || haystack.includes("pkce_verifier_missing")) {
    return "Nao foi possivel validar este link neste navegador. Solicite um novo link.";
  }

  if (haystack.includes("otp_expired") || haystack.includes("expired")) {
    return "Link invalido ou expirado. Solicite uma nova redefinicao.";
  }

  if (haystack.includes("invalid") || haystack.includes("access_denied")) {
    return "Link invalido ou expirado. Solicite uma nova redefinicao.";
  }

  return "Nao foi possivel validar o link de redefinicao.";
}

export default function ClientPortalResetPasswordCard({
  slug,
  storeName,
  logoUrl,
  primaryColor,
  defaultEmail = "",
  defaultPortalToken = "",
}: {
  slug: string;
  storeName: string;
  logoUrl: string;
  primaryColor: string;
  defaultEmail?: string;
  defaultPortalToken?: string;
}) {
  const router = useRouter();
  const searchParams = useSearchParams();
  const supabase = useMemo(() => getSupabaseClient(), []);
  const [email, setEmail] = useState(defaultEmail);
  const [portalAccessToken, setPortalAccessToken] = useState(defaultPortalToken);
  const [password, setPassword] = useState("");
  const [confirmPassword, setConfirmPassword] = useState("");
  const [ready, setReady] = useState(false);
  /* Só vale como recuperação a sessão que NASCEU do link do e-mail nesta
     abertura da página. Uma sessão qualquer guardada no navegador (do login
     com Google, ou de uma redefinição antiga) não é permissão para trocar a
     senha: quem senta no mesmo computador depois cairia direto no formulário
     e poderia trocar a senha da pessoa sem saber a atual. */
  const [veioDoLink, setVeioDoLink] = useState(false);
  /* O código do link que o próprio sistema manda por e-mail
     (password-reset/request). Quem confere é o servidor, na hora de salvar. */
  const [codigoDoEmail, setCodigoDoEmail] = useState("");
  const [requesting, setRequesting] = useState(false);
  const [saving, setSaving] = useState(false);
  const [message, setMessage] = useState<{ type: "success" | "error"; text: string } | null>(null);

  useEffect(() => {
    const emailFromQuery = String(searchParams.get("email") || "").trim();
    const tokenFromQuery = String(searchParams.get("portal_token") || "").trim();
    const codigoFromQuery = String(searchParams.get("codigo") || "").trim();
    if (emailFromQuery) setEmail(emailFromQuery);
    if (tokenFromQuery) setPortalAccessToken(tokenFromQuery);
    if (codigoFromQuery) {
      setCodigoDoEmail(codigoFromQuery);
      const semCodigo = new URL(window.location.href);
      semCodigo.searchParams.delete("codigo");
      window.history.replaceState({}, document.title, semCodigo.toString());
    }
  }, [searchParams]);

  useEffect(() => {
    let active = true;

    async function run() {
      try {
        const url = new URL(window.location.href);
        const code = url.searchParams.get("code");
        const tokenHashFromQuery = url.searchParams.get("token_hash");
        const accessTokenFromQuery = url.searchParams.get("access_token");
        const refreshTokenFromQuery = url.searchParams.get("refresh_token");
        const typeFromQuery = url.searchParams.get("type");
        const errorFromQuery = url.searchParams.get("error");
        const errorCodeFromQuery = url.searchParams.get("error_code");
        const errorDescriptionFromQuery = url.searchParams.get("error_description");
        const hashParams = new URLSearchParams((url.hash || "").replace(/^#/, ""));
        const tokenHashFromHash = hashParams.get("token_hash");
        const accessTokenFromHash = hashParams.get("access_token");
        const refreshTokenFromHash = hashParams.get("refresh_token");
        const typeFromHash = hashParams.get("type");
        const errorFromHash = hashParams.get("error");
        const errorCodeFromHash = hashParams.get("error_code");
        const errorDescriptionFromHash = hashParams.get("error_description");

        const tokenHash = tokenHashFromQuery || tokenHashFromHash;
        const accessToken = accessTokenFromQuery || accessTokenFromHash;
        const refreshToken = refreshTokenFromQuery || refreshTokenFromHash;
        const type = typeFromQuery || typeFromHash;
        const error = errorFromQuery || errorFromHash;
        const errorCode = errorCodeFromQuery || errorCodeFromHash;
        const errorDescription = errorDescriptionFromQuery || errorDescriptionFromHash;

        if ((error || errorCode) && active) {
          setMessage({
            type: "error",
            text: mapResetError(error, errorCode, errorDescription),
          });
        }

        /* `linkValidado` é o que separa "cheguei pelo e-mail" de "tinha uma
           sessão velha aqui". Só o primeiro abre o formulário de nova senha. */
        let linkValidado = false;

        if (tokenHash && type === "recovery") {
          const { error: verifyError } = await supabase.auth.verifyOtp({
            token_hash: tokenHash,
            type: "recovery",
          });

          if (verifyError && active) {
            setMessage({ type: "error", text: mapResetError(verifyError.name, null, verifyError.message) });
          }
          linkValidado = !verifyError;
        } else if (accessToken && refreshToken && type === "recovery") {
          const { error: sessionError } = await supabase.auth.setSession({
            access_token: accessToken,
            refresh_token: refreshToken,
          });

          if (sessionError && active) {
            setMessage({ type: "error", text: mapResetError(sessionError.name, null, sessionError.message) });
          }
          linkValidado = !sessionError;
        } else if (code) {
          const { error: exchangeError } = await supabase.auth.exchangeCodeForSession(code);

          if (exchangeError && active) {
            setMessage({ type: "error", text: mapResetError(exchangeError.name, null, exchangeError.message) });
          }
          linkValidado = !exchangeError;
        }

        const { data: sessionData } = await supabase.auth.getSession();
        const session = sessionData.session;

        if (!active) return;

        if (linkValidado && session) {
          setVeioDoLink(true);
          if (session.user?.email) setEmail(session.user.email);
        }

        if (code || tokenHash || accessToken || refreshToken || error || errorCode) {
          const cleanUrl = new URL(window.location.href);
          cleanUrl.search = "";
          cleanUrl.hash = "";
          if (email) cleanUrl.searchParams.set("email", email);
          window.history.replaceState({}, document.title, cleanUrl.toString());
        }
      } finally {
        if (active) setReady(true);
      }
    }

    void run();

    const { data: authListener } = supabase.auth.onAuthStateChange((event, session) => {
      if (!active) return;
      /* O próprio SDK pode consumir o link antes de a página ler a URL. Nesse
         caso é este evento que avisa — e só ele: SIGNED_IN acontece em
         qualquer login e não prova que houve pedido de recuperação. */
      if (event === "PASSWORD_RECOVERY") {
        setVeioDoLink(Boolean(session));
        if (session?.user?.email) setEmail(session.user.email);
      }
      if (event === "SIGNED_OUT") {
        setVeioDoLink(false);
      }
    });

    return () => {
      active = false;
      authListener.subscription.unsubscribe();
    };
  }, [email, supabase.auth]);

  const canSetPassword = veioDoLink || Boolean(portalAccessToken) || Boolean(codigoDoEmail);

  async function handleRequestReset(event: React.FormEvent) {
    event.preventDefault();
    if (requesting) return;
    setRequesting(true);
    setMessage(null);

    try {
      const response = await fetch("/api/client-portal/password-reset/request", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          slug,
          email,
        }),
      });

      const payload = (await response.json().catch(() => null)) as { error?: string; message?: string } | null;
      if (!response.ok) {
        throw new Error(payload?.error || "Nao foi possivel enviar o link de redefinicao.");
      }

      setMessage({
        type: "success",
        text: payload?.message || "Se houver um cadastro correspondente, enviaremos um link para redefinir a senha.",
      });
    } catch (error) {
      const text =
        typeof error === "object" && error && "message" in error && typeof error.message === "string"
          ? error.message
          : "Nao foi possivel enviar o link de redefinicao.";
      setMessage({ type: "error", text });
    } finally {
      setRequesting(false);
    }
  }

  async function handleSavePassword(event: React.FormEvent) {
    event.preventDefault();
    if (saving) return;
    setSaving(true);
    setMessage(null);

    try {
      if (password.length < 8) {
        throw new Error("A nova senha precisa ter pelo menos 8 caracteres.");
      }

      if (password !== confirmPassword) {
        throw new Error("As senhas nao conferem.");
      }

      if (codigoDoEmail) {
        const respostaDoCodigo = await fetch("/api/client-portal/password-reset/confirm", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({ slug, password, codigo: codigoDoEmail }),
        });
        const dadosDoCodigo = (await respostaDoCodigo.json().catch(() => null)) as { error?: string; email?: string } | null;
        if (!respostaDoCodigo.ok) {
          throw new Error(dadosDoCodigo?.error || "Nao foi possivel atualizar a senha.");
        }
        /* O link já foi usado: não serve para uma segunda troca. */
        setCodigoDoEmail("");

        const emailDaConta = String(dadosDoCodigo?.email || email).trim();
        const respostaDoLogin = await fetch("/api/client-portal/login", {
          method: "POST",
          headers: { "content-type": "application/json" },
          body: JSON.stringify({ slug, identifier: emailDaConta, password, next: `/${slug}/cliente` }),
        });
        const dadosDoLogin = (await respostaDoLogin.json().catch(() => null)) as { redirect_url?: string } | null;
        if (respostaDoLogin.ok && dadosDoLogin?.redirect_url) {
          window.location.assign(dadosDoLogin.redirect_url);
          return;
        }
        setMessage({ type: "success", text: "Senha redefinida com sucesso. Entre com a sua nova senha." });
        setPassword("");
        setConfirmPassword("");
        setTimeout(() => {
          router.push(`/${slug}/cliente/login?mode=login&success=${encodeURIComponent("Senha redefinida com sucesso.")}`);
        }, 1200);
        return;
      }

      if (portalAccessToken) {
        const confirmResponse = await fetch("/api/client-portal/password-reset/confirm", {
          method: "POST",
          headers: {
            "content-type": "application/json",
          },
          body: JSON.stringify({
            slug,
            password,
            portalToken: portalAccessToken,
          }),
        });

        const confirmPayload = (await confirmResponse.json().catch(() => null)) as { error?: string } | null;
        if (!confirmResponse.ok) {
          throw new Error(confirmPayload?.error || "Nao foi possivel atualizar a senha.");
        }

        window.location.assign(
          `/api/client-portal/session/bootstrap?token=${encodeURIComponent(portalAccessToken)}&next=${encodeURIComponent(`/${slug}/cliente`)}`
        );
        return;
      }

      const { data: sessionData } = await supabase.auth.getSession();
      const accessToken = sessionData.session?.access_token || "";
      const sessionEmail = sessionData.session?.user?.email || email;

      if (!accessToken || !sessionEmail) {
        throw new Error("Link invalido ou expirado. Solicite uma nova redefinicao.");
      }

      const confirmResponse = await fetch("/api/client-portal/password-reset/confirm", {
        method: "POST",
        headers: {
          "content-type": "application/json",
          authorization: `Bearer ${accessToken}`,
        },
        body: JSON.stringify({
          slug,
          password,
        }),
      });

      const confirmPayload = (await confirmResponse.json().catch(() => null)) as { error?: string } | null;
      if (!confirmResponse.ok) {
        throw new Error(confirmPayload?.error || "Nao foi possivel atualizar a senha.");
      }

      const loginResponse = await fetch("/api/client-portal/login", {
        method: "POST",
        headers: { "content-type": "application/json" },
        body: JSON.stringify({
          slug,
          identifier: sessionEmail,
          password,
          next: `/${slug}/cliente`,
        }),
      });

      const loginPayload = (await loginResponse.json().catch(() => null)) as { error?: string; redirect_url?: string } | null;
      await supabase.auth.signOut();

      if (!loginResponse.ok || !loginPayload?.redirect_url) {
        setMessage({
          type: "success",
          text: "Senha redefinida com sucesso. Entre novamente no portal com sua nova senha.",
        });
        setPassword("");
        setConfirmPassword("");
        setTimeout(() => {
          router.push(`/${slug}/cliente/login?mode=login&success=${encodeURIComponent("Senha redefinida com sucesso.")}`);
        }, 1200);
        return;
      }

      window.location.assign(loginPayload.redirect_url);
    } catch (error) {
      const text =
        typeof error === "object" && error && "message" in error && typeof error.message === "string"
          ? error.message
          : "Nao foi possivel salvar a nova senha.";
      setMessage({ type: "error", text });
    } finally {
      setSaving(false);
    }
  }

  return (
    <div className="relative min-h-screen bg-white selection:bg-zinc-100">
      <div className="flex min-h-screen flex-col items-center justify-center p-4 sm:p-8">
        <motion.div
          initial={{ opacity: 0, y: 12 }}
          animate={{ opacity: 1, y: 0 }}
          transition={{ duration: 0.4 }}
          className="w-full max-w-[440px]"
        >
          <div className="mb-10 text-center">
            {logoUrl ? (
              <Image
                src={logoUrl}
                alt={storeName}
                width={80}
                height={80}
                className="mx-auto mb-6 h-16 w-auto object-contain"
                unoptimized
              />
            ) : (
              <div
                className="mx-auto mb-6 flex h-16 w-16 items-center justify-center rounded-[20px] text-xl font-bold"
                style={{ color: getAccessibleAccent(primaryColor), backgroundColor: hexToRgba(primaryColor, 0.08) }}
              >
                {storeName.slice(0, 2).toUpperCase()}
              </div>
            )}
            <div
              className="mx-auto mb-4 inline-flex items-center gap-2 rounded-[10px] px-3 py-1.5 text-[12px] font-semibold"
              style={{ backgroundColor: hexToRgba(primaryColor, 0.08), color: getAccessibleAccent(primaryColor) }}
            >
              <span className="h-1.5 w-1.5 rounded-full" style={{ backgroundColor: primaryColor, color: getReadableTextColor(primaryColor) }} />
              <span>{canSetPassword ? "Nova senha" : "Acesso ao portal"}</span>
            </div>
            <h1 className="text-2xl font-semibold tracking-tight text-zinc-900">
              {canSetPassword ? "Defina sua nova senha" : "Redefinir senha"}
            </h1>
            <p className="mt-2 text-sm text-zinc-500">
              {canSetPassword
                ? "Confirme uma nova senha para voltar ao portal do cliente."
                : "Informe o e-mail do cadastro para receber o link de redefinicao."}
            </p>
          </div>

          {!ready ? (
            <div className="flex items-center justify-center gap-2 rounded-xl border border-zinc-200 bg-white px-4 py-4 text-sm text-zinc-600">
              <Loader2 className="h-4 w-4 animate-spin" />
              Carregando...
            </div>
          ) : canSetPassword ? (
            <form onSubmit={handleSavePassword} className="space-y-4">
              <div className="space-y-1">
                <label className="text-[13px] font-medium text-zinc-700">E-mail do acesso</label>
                <div className="flex h-[50px] items-center rounded-xl border border-zinc-200 bg-zinc-50 px-4 text-sm text-zinc-700">
                  {email || "Nao identificado"}
                </div>
              </div>

              <div className="space-y-1">
                <label className="text-[13px] font-medium text-zinc-700">Nova senha</label>
                <div className="relative">
                  <LockKeyhole className="pointer-events-none absolute left-4 top-1/2 h-4 w-4 -translate-y-1/2 text-zinc-400" />
                  <input
                    type="password"
                    value={password}
                    onChange={(event) => setPassword(event.target.value)}
                    placeholder="Minimo 8 caracteres"
                    className="w-full rounded-xl border border-zinc-200 bg-white py-3 pl-11 pr-4 text-sm text-zinc-900 outline-none transition-colors placeholder:text-zinc-400 focus:border-zinc-400 focus:ring-0"
                    autoComplete="new-password"
                    minLength={8}
                    required
                  />
                </div>
              </div>

              <div className="space-y-1">
                <label className="text-[13px] font-medium text-zinc-700">Confirmar nova senha</label>
                <div className="relative">
                  <LockKeyhole className="pointer-events-none absolute left-4 top-1/2 h-4 w-4 -translate-y-1/2 text-zinc-400" />
                  <input
                    type="password"
                    value={confirmPassword}
                    onChange={(event) => setConfirmPassword(event.target.value)}
                    placeholder="Repita a nova senha"
                    className="w-full rounded-xl border border-zinc-200 bg-white py-3 pl-11 pr-4 text-sm text-zinc-900 outline-none transition-colors placeholder:text-zinc-400 focus:border-zinc-400 focus:ring-0"
                    autoComplete="new-password"
                    minLength={8}
                    required
                  />
                </div>
              </div>

              {message ? (
                <div
                  className={`rounded-xl border px-4 py-3 text-[13px] ${
                    message.type === "success"
                      ? "border-emerald-100 bg-emerald-50 text-emerald-700"
                      : "border-rose-100 bg-rose-50 text-rose-600"
                  }`}
                >
                  {message.text}
                </div>
              ) : null}

              <button
                type="submit"
                disabled={saving}
                className="mt-2 flex w-full items-center justify-center gap-2 rounded-xl px-4 py-3 text-sm font-semibold text-white transition-opacity hover:opacity-90 disabled:opacity-60"
                style={{ backgroundColor: primaryColor, color: getReadableTextColor(primaryColor) }}
              >
                {saving ? <Loader2 className="h-4 w-4 animate-spin" /> : <ArrowRight className="h-4 w-4" />}
                {saving ? "Salvando..." : "Salvar e entrar no portal"}
              </button>
            </form>
          ) : (
            <form onSubmit={handleRequestReset} className="space-y-4">
              <div className="space-y-1">
                <label className="text-[13px] font-medium text-zinc-700">E-mail do cadastro</label>
                <div className="relative">
                  <Mail className="pointer-events-none absolute left-4 top-1/2 h-4 w-4 -translate-y-1/2 text-zinc-400" />
                  <input
                    type="email"
                    value={email}
                    onChange={(event) => setEmail(event.target.value)}
                    placeholder="nome@email.com"
                    className="w-full rounded-xl border border-zinc-200 bg-white py-3 pl-11 pr-4 text-sm text-zinc-900 outline-none transition-colors placeholder:text-zinc-400 focus:border-zinc-400 focus:ring-0"
                    autoComplete="email"
                    required
                  />
                </div>
              </div>

              {message ? (
                <div
                  className={`rounded-xl border px-4 py-3 text-[13px] ${
                    message.type === "success"
                      ? "border-emerald-100 bg-emerald-50 text-emerald-700"
                      : "border-rose-100 bg-rose-50 text-rose-600"
                  }`}
                >
                  {message.text}
                </div>
              ) : null}

              <button
                type="submit"
                disabled={requesting}
                className="mt-2 flex w-full items-center justify-center gap-2 rounded-xl px-4 py-3 text-sm font-semibold text-white transition-opacity hover:opacity-90 disabled:opacity-60"
                style={{ backgroundColor: primaryColor, color: getReadableTextColor(primaryColor) }}
              >
                {requesting ? <Loader2 className="h-4 w-4 animate-spin" /> : <ArrowRight className="h-4 w-4" />}
                {requesting ? "Enviando..." : "Enviar link de redefinicao"}
              </button>
            </form>
          )}

          <div className="mt-8 text-center">
            <Link href={`/${slug}/cliente/login`} className="text-[13px] font-medium text-zinc-500 hover:text-zinc-900">
              &larr; Voltar para o login
            </Link>
          </div>
        </motion.div>
      </div>
    </div>
  );
}
