import { useEffect, useRef, useState } from "react";
import { Trans, useTranslation } from "react-i18next";
import { useWizard } from "react-use-wizard";
import { shallowEqual } from "react-redux";

import StyledButton from "@/components/styled/Button";
import { BASE_ORIGIN, tokenHeader } from "@/app/config";
import { getLocalAuthData, compareVersion } from "@/utils";
import { useAppSelector } from "@/app/store";
import { useGetAutoTunnelInfoQuery } from "@/app/services/server";

const REQUIRED_VERSION = "0.5.19";

type Phase = "prompt" | "starting" | "done" | "error";

const COUNTDOWN_SECONDS = 10;

interface SseEvent {
  event: string;
  message: string;
  url: string | null;
  progress: number | null;
}

export default function GetPublicDomain() {
  const { t } = useTranslation("welcome", { keyPrefix: "onboarding" });
  const { t: tCommon } = useTranslation();
  const { nextStep } = useWizard();
  const currentVersion = useAppSelector((store) => store.server.version, shallowEqual);
  const { data: autoInfo } = useGetAutoTunnelInfoQuery();

  const isLocalhost = /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?$/.test(location.origin);

  const [phase, setPhase] = useState<Phase>("prompt");
  const [logs, setLogs] = useState<string[]>([]);
  const [tunnelUrl, setTunnelUrl] = useState<string | null>(null);
  const [errorMsg, setErrorMsg] = useState<string | null>(null);
  const [countdown, setCountdown] = useState(COUNTDOWN_SECONDS);
  const abortRef = useRef<AbortController | null>(null);
  const countRef = useRef<ReturnType<typeof setInterval> | null>(null);

  useEffect(() => {
    return () => {
      abortRef.current?.abort();
      if (countRef.current) clearInterval(countRef.current);
    };
  }, []);

  const addLog = (msg: string) =>
    setLogs((prev) => [...prev.slice(-29), msg]);

  function startCountdown(url: string) {
    setTunnelUrl(url);
    setPhase("done");
    if (!isLocalhost) return;
    let remaining = COUNTDOWN_SECONDS;
    setCountdown(remaining);
    countRef.current = setInterval(() => {
      remaining -= 1;
      setCountdown(remaining);
      if (remaining <= 0) {
        clearInterval(countRef.current!);
        window.location.href = url;
      }
    }, 1000);
  }

  const handleYes = async () => {
    setPhase("starting");
    setLogs([]);
    setErrorMsg(null);

    const ctrl = new AbortController();
    abortRef.current = ctrl;

    try {
      const { token } = getLocalAuthData();
      const resp = await fetch(`${BASE_ORIGIN}/api/admin/cloudflared/start`, {
        method: "POST",
        headers: { [tokenHeader]: token },
        signal: ctrl.signal,
      });

      if (!resp.ok || !resp.body) {
        setPhase("error");
        setErrorMsg(`HTTP ${resp.status}`);
        return;
      }

      const reader = resp.body.getReader();
      const decoder = new TextDecoder();
      let buf = "";

      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        buf += decoder.decode(value, { stream: true });

        const parts = buf.split("\n\n");
        buf = parts.pop() ?? "";

        for (const part of parts) {
          const line = part.trim();
          if (!line.startsWith("data:")) continue;
          try {
            const evt: SseEvent = JSON.parse(line.slice("data:".length).trim());
            addLog(evt.message);
            if (evt.event === "url" || evt.event === "already_running") {
              reader.cancel();
              startCountdown(evt.url!);
              return;
            }
            if (evt.event === "error" || evt.event === "stopped") {
              reader.cancel();
              setPhase("error");
              setErrorMsg(evt.message);
              return;
            }
          } catch {
            // ignore malformed lines
          }
        }
      }
    } catch (err: any) {
      if (err?.name !== "AbortError") {
        setPhase("error");
        setErrorMsg(String(err));
      }
    }
  };

  if (currentVersion && compareVersion(currentVersion, REQUIRED_VERSION) < 0) {
    return (
      <div className="flex-center flex-col h-full text-center gap-6 dark:text-gray-100 px-4">
        <div className="flex flex-col gap-2 items-center border border-solid border-orange-500 p-4 rounded-lg max-w-sm">
          <span className="text-gray-600 dark:text-gray-300 text-sm">
            <Trans i18nKey={"server_update.version_needed"}>
              <strong className="font-bold">{{ version: REQUIRED_VERSION }}</strong>
            </Trans>
          </span>
          <span className="text-gray-600 dark:text-gray-300 text-sm">
            <Trans i18nKey={"server_update.current_version"}>
              <strong className="font-bold">{{ version: currentVersion }}</strong>
            </Trans>
          </span>
          <span className="text-gray-400 text-sm">{tCommon("server_update.update_tip")}</span>
          <a
            className="text-blue-500 underline text-sm"
            href="https://doc.voce.chat/install/docker"
            target="_blank"
            rel="noopener noreferrer"
          >
            {tCommon("server_update.howto")} 📖
          </a>
        </div>
        <StyledButton className="w-24 h-11 ghost" onClick={nextStep}>
          {t("tunnel_opt_in_skip")}
        </StyledButton>
      </div>
    );
  }

  if (phase === "prompt") {
    return (
      <div className="flex-center flex-col h-full text-center gap-8 dark:text-gray-100 px-4">
        <span className="text-2xl font-bold">{t("tunnel_opt_in_title")}</span>
        <div className="flex gap-4">
          <StyledButton className="w-24 h-11" onClick={handleYes}>
            {t("tunnel_opt_in_yes")}
          </StyledButton>
          <StyledButton className="w-24 h-11 ghost" onClick={nextStep}>
            {t("tunnel_opt_in_skip")}
          </StyledButton>
        </div>
      </div>
    );
  }

  if (phase === "starting") {
    return (
      <div className="flex-center flex-col h-full text-center gap-6 dark:text-gray-100 px-4">
        <div className="w-10 h-10 border-4 border-primary-400 border-t-transparent rounded-full animate-spin" />
        <span className="text-lg font-semibold">{t("tunnel_progress")}</span>
        {logs.length > 0 && (
          <div className="w-full md:w-[480px] p-3 bg-gray-50 dark:bg-gray-800 rounded-lg font-mono text-xs text-gray-500 dark:text-gray-400 max-h-40 overflow-y-auto text-left flex flex-col gap-0.5">
            {logs.map((log, i) => (
              <div key={i}>{log}</div>
            ))}
          </div>
        )}
      </div>
    );
  }

  if (phase === "done" && tunnelUrl) {
    return (
      <div className="flex-center flex-col h-full text-center gap-6 dark:text-gray-100 px-4 md:max-w-md m-auto">
        {isLocalhost && (
          <div className="w-10 h-10 border-4 border-green-400 border-t-transparent rounded-full animate-spin" />
        )}
        <a
          href={tunnelUrl}
          target="_blank"
          rel="noopener noreferrer"
          className="font-mono text-sm break-all text-green-600 dark:text-green-400 underline"
        >
          {tunnelUrl}
        </a>
        {isLocalhost ? (
          <span className="text-lg font-semibold">
            {t("tunnel_redirect_countdown", { seconds: countdown })}
          </span>
        ) : (
          <StyledButton className="w-32 h-11" onClick={nextStep}>
            {t("tunnel_opt_in_skip")}
          </StyledButton>
        )}
      </div>
    );
  }

  if (phase === "error") {
    return (
      <div className="flex-center flex-col h-full text-center gap-6 dark:text-gray-100 px-4">
        <span className="text-lg font-semibold text-red-500">{t("tunnel_error")}</span>
        {errorMsg && (
          <p className="text-sm text-gray-500 dark:text-gray-400 break-all max-w-sm">
            {errorMsg}
          </p>
        )}
        <StyledButton className="w-24 h-11" onClick={nextStep}>
          {t("tunnel_opt_in_skip")}
        </StyledButton>
      </div>
    );
  }

  return null;
}
