"use client";

import { useEffect, useState, useRef } from "react";
import { motion, AnimatePresence } from "framer-motion";
import {
  Shield,
  ShieldAlert,
  ShieldCheck,
  Loader2,
  Terminal,
} from "lucide-react";
import { CyberButton } from "@/components/ui/cyber-button";
import { Dictionary } from "@/lib/IDict";

// Telegram Login Widget вызывает этот колбэк из глобального window после успешной
// авторизации в самом Telegram — вешаем на него типизацию, т.к. виджет грузится
// сторонним <script> и не завязан на React-модель.
declare global {
  interface Window {
    onTelegramAuth: (user: any) => void;
  }
}

interface AuthClientProps {
  dict: Dictionary["auth"];
  lang: string;
  /**
   * Origin ЛК (netrunner-backend) и база API — приходят как props из
   * серверного `page.tsx`, а не читаются напрямую из
   * `process.env.NEXT_PUBLIC_*` здесь: этот файл — `"use client"`, и
   * Next.js инлайнит `NEXT_PUBLIC_*` в клиентский бандл на этапе `next
   * build`, а не читает их заново при старте контейнера. Один и тот же
   * собранный образ используется и для прода, и для дев-деплоя — если бы
   * значение было зашито в бандл на сборке, dev-окружение стучалось бы в
   * прод-бэкенд независимо от `environment:` в docker-compose. Читая их в
   * серверном компоненте (`page.tsx`, исполняется заново на каждый запрос)
   * и прокидывая пропсами, получаем настоящую runtime-конфигурируемость
   * из одного и того же образа.
   */
  accountOrigin: string;
  apiBase: string;
  botUsername: string;
}

/**
 * Экран авторизации через Telegram Login Widget.
 *
 * Сессия — исключительно HttpOnly cookie, которую ставит netrunner-backend
 * (сабдомен account.netrunner-vpn.com, общий родительский домен
 * `.netrunner-vpn.com` — cookie видна и лендингу, и ЛК). Здесь ничего не
 * хранится и не читается на стороне JS: ни localStorage, ни query/hash с
 * токеном — раньше лендинг таскал токен в `localStorage["nrxp_token"]` и в
 * URL, это ровно то, чего требовалось избежать.
 *
 * Раз ЛК физически находится на другом сабдомене, после успешного логина —
 * полный переход браузера на `${accountOrigin}/profile`, а не
 * клиентский роутинг (страницы `/profile` в самом лендинге нет и не будет).
 */
export function AuthClient({
  dict,
  lang,
  accountOrigin,
  apiBase,
  botUsername,
}: AuthClientProps) {
  const [status, setStatus] = useState<
    "processing" | "granted" | "denied" | "awaiting"
  >("processing");
  const [logs, setLogs] = useState<string[]>([]);
  const tgContainerRef = useRef<HTMLDivElement>(null);
  const initialized = useRef(false);
  const widgetInjected = useRef(false);

  useEffect(() => {
    // Защита от двойного запуска в React 18 Strict Mode (эффект монтируется дважды
    // в dev-режиме) — без этого флага мы бы дважды дернули /users/me и задвоили логи.
    if (initialized.current) return;
    initialized.current = true;

    const authenticate = async () => {
      setLogs((prev) => [...prev, `> ${dict.processing}`]);
      setLogs((prev) => [...prev, `> ${dict.verifying}`]);

      try {
        const res = await fetch(`${apiBase}/users/me`, {
          credentials: "include",
        });

        if (res.ok) {
          setLogs((prev) => [...prev, dict.logs.sigValid]);
          setStatus("granted");
          setLogs((prev) => [...prev, `> ${dict.redirecting}`]);
          setTimeout(() => {
            window.location.href = `${accountOrigin}/profile`;
          }, 1500);
        } else {
          setLogs((prev) => [...prev, dict.logs.waitInit]);
          setStatus("awaiting");
        }
      } catch {
        setLogs((prev) => [...prev, dict.logs.coreOffline]);
        setStatus("denied");
      }
    };

    authenticate();
  }, [dict, apiBase, accountOrigin]);

  // Регистрируем глобальный колбэк для Telegram Login Widget: сам виджет
  // подключается сторонним script-тегом ниже (см. следующий useEffect) и после
  // логина в Telegram вызывает window.onTelegramAuth с данными пользователя.
  useEffect(() => {
    window.onTelegramAuth = async (user: any) => {
      setStatus("processing");
      setLogs((prev) => [...prev, dict.logs.authPayload, dict.logs.verifyHmac]);
      try {
        const res = await fetch(`${apiBase}/auth/telegram`, {
          method: "POST",
          credentials: "include",
          headers: { "Content-Type": "application/json" },
          body: JSON.stringify(user),
        });

        if (res.ok) {
          setLogs((prev) => [
            ...prev,
            dict.logs.sigValid,
            `> ${dict.redirecting}`,
          ]);
          setStatus("granted");
          setTimeout(() => {
            window.location.href = `${accountOrigin}/profile`;
          }, 1500);
        } else {
          setLogs((prev) => [...prev, dict.logs.invalidSig]);
          setStatus("denied");
        }
      } catch (e) {
        setLogs((prev) => [...prev, dict.logs.networkError]);
        setStatus("denied");
      }
    };
  }, [dict, lang, apiBase, accountOrigin]);

  // Инжектим официальный Telegram Widget script только когда реально дошли до
  // экрана "awaiting" (нет токена) — виджет сам рисует кнопку логина в контейнере
  // и после успеха вызывает window.onTelegramAuth. widgetInjected защищает от
  // повторной вставки script-тега при повторных ререндерах.
  useEffect(() => {
    if (
      status === "awaiting" &&
      tgContainerRef.current &&
      !widgetInjected.current
    ) {
      widgetInjected.current = true;
      const script = document.createElement("script");
      script.src = "https://telegram.org/js/telegram-widget.js?22";
      script.async = true;
      script.setAttribute("data-telegram-login", botUsername);
      script.setAttribute("data-size", "large");
      script.setAttribute("data-onauth", "onTelegramAuth(user)");
      script.setAttribute("data-request-access", "write");
      tgContainerRef.current.appendChild(script);
    }
  }, [status, botUsername]);

  return (
    <div className="min-h-screen pt-32 pb-24 px-4 container mx-auto max-w-2xl relative flex flex-col items-center justify-center font-mono">
      <div className="absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-[80vw] h-[80vw] max-w-150 max-h-150 bg-primary/5 blur-[120px] rounded-full -z-10 pointer-events-none" />
      <motion.div
        initial={{ opacity: 0, y: 20 }}
        animate={{ opacity: 1, y: 0 }}
        className="w-full bg-card/40 backdrop-blur-xl border border-border/50 rounded-2xl p-8 md:p-12 shadow-2xl relative overflow-hidden"
      >
        <div className="flex flex-col items-center mb-10 text-center">
          <div className="mb-8 relative">
            {status === "processing" && (
              <div className="relative">
                <div className="absolute inset-0 bg-primary/20 blur-xl rounded-full" />
                <Shield className="w-20 h-20 text-primary animate-pulse relative z-10" />
              </div>
            )}
            {status === "granted" && (
              <div className="relative">
                <div className="absolute inset-0 bg-secondary/20 blur-xl rounded-full" />
                <ShieldCheck className="w-20 h-20 text-secondary drop-shadow-[0_0_15px_rgba(0,229,242,0.8)] relative z-10" />
              </div>
            )}
            {status === "denied" && (
              <div className="relative">
                <div className="absolute inset-0 bg-destructive/20 blur-xl rounded-full" />
                <ShieldAlert className="w-20 h-20 text-destructive drop-shadow-[0_0_15px_rgba(255,0,0,0.8)] relative z-10" />
              </div>
            )}
            {status === "awaiting" && (
              <div className="relative">
                <div className="absolute inset-0 bg-secondary/20 blur-xl rounded-full" />
                <Terminal className="w-20 h-20 text-secondary drop-shadow-[0_0_15px_rgba(0,229,242,0.8)] relative z-10" />
              </div>
            )}
          </div>
          <h1 className="text-2xl md:text-3xl font-black tracking-widest text-foreground uppercase">
            {status === "processing"
              ? dict.title
              : status === "granted"
                ? dict.granted
                : status === "awaiting"
                  ? dict.awaiting
                  : dict.denied}
          </h1>
        </div>

        <div className="bg-background/80 border border-border/50 rounded-2xl p-6 font-mono text-sm text-muted-foreground/80 min-h-35 flex flex-col justify-end space-y-3 mb-8 shadow-inner">
          <AnimatePresence>
            {logs.map((log, i) => (
              <motion.div
                key={i}
                initial={{ opacity: 0, x: -10 }}
                animate={{ opacity: 1, x: 0 }}
                className={
                  log.includes("[OK]") || log.includes("[OK]")
                    ? "text-secondary font-bold drop-shadow-[0_0_5px_rgba(0,229,242,0.5)]"
                    : log.includes("[FAIL]") || log.includes("[ОШИБКА]")
                      ? "text-destructive font-bold drop-shadow-[0_0_5px_rgba(255,0,0,0.5)]"
                      : ""
                }
              >
                {log}
              </motion.div>
            ))}
          </AnimatePresence>

          {status === "processing" && (
            <div className="flex items-center gap-2 text-primary mt-2">
              <Loader2 className="w-4 h-4 animate-spin" />
              <span className="animate-pulse font-bold text-lg leading-none">
                _
              </span>
            </div>
          )}
        </div>

        {status === "denied" && (
          <motion.div
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            className="flex flex-col items-center text-center gap-8"
          >
            <p className="text-sm text-muted-foreground leading-relaxed max-w-md">
              {dict.noToken}
            </p>
            <CyberButton
              href={`https://t.me/${botUsername}`}
              variant="primary"
              className="w-full sm:w-auto"
            >
              <span className="flex items-center gap-2">
                <Terminal className="w-4 h-4" />
                {dict.toBot}
              </span>
            </CyberButton>
          </motion.div>
        )}

        {status === "awaiting" && (
          <motion.div
            initial={{ opacity: 0, y: 10 }}
            animate={{ opacity: 1, y: 0 }}
            className="flex flex-col items-center text-center gap-6 mt-4"
          >
            <p className="text-sm text-muted-foreground leading-relaxed max-w-md">
              {dict.authPrompt}
            </p>
            <div
              ref={tgContainerRef}
              className="min-h-[40px] flex items-center justify-center"
            />
          </motion.div>
        )}
      </motion.div>
    </div>
  );
}
