import { useCallback, useEffect, useRef } from "react";

import { usePlayerSessionStore } from "@/stores/player-session-store";
import { useErrorStore } from "@/stores/error-store";
import {
  isIframeOriginAllowed,
  loadIframeAllowedOrigins,
  resolvePostMessageTargetOrigin,
} from "@/lib/iframe-origins";

/** Token 过期前警告阈值（毫秒） */
const TOKEN_WARNING_THRESHOLD = 60 * 1000; // 1 分钟

/** 最大重试次数 */
const MAX_RETRY = 3;

/**
 * Token 自动续签 Hook
 *
 * 功能：
 * 1. 监听主站 postMessage 发送的新 Token
 * 2. 自动检测 Token 过期时间并在过期前静默续签
 * 3. 支持手动触发刷新
 * 4. 刷新失败时提示用户返回主站
 */
export function useTokenRefresh(): {
  /** 手动触发 Token 刷新 */
  refreshToken: () => Promise<void>;
  /** 当前 Token 剩余有效时间（毫秒），-1 表示未知 */
  getTokenRemainingTime: () => number;
  /** 是否即将过期 */
  isTokenExpiringSoon: () => boolean;
} {
  const bearerToken = usePlayerSessionStore((state) => state.bearerToken);
  const setBearerToken = usePlayerSessionStore((state) => state.setBearerToken);
  const setServerError = useErrorStore((state) => state.setServerError);
  const clearServerError = useErrorStore((state) => state.clearServerError);

  const refreshTimerRef = useRef<NodeJS.Timeout | null>(null);
  const retryCountRef = useRef(0);

  /**
   * 解析 JWT 的 exp 字段
   * @returns exp 时间戳（秒），解析失败返回 null
   */
  const parseTokenExp = useCallback((token: string | null): number | null => {
    if (!token) return null;

    try {
      // JWT 格式：header.payload.signature
      const parts = token.split(".");
      if (parts.length !== 3) return null;

      // Base64 解码 payload
      const payload = JSON.parse(atob(parts[1]));
      return payload.exp ?? null;
    } catch {
      return null;
    }
  }, []);

  /**
   * 获取 Token 剩余有效时间
   * @returns 剩余毫秒数，-1 表示未知
   */
  const getTokenRemainingTime = useCallback((): number => {
    const exp = parseTokenExp(bearerToken);
    if (!exp) return -1;

    const now = Math.floor(Date.now() / 1000);
    return Math.max(0, (exp - now) * 1000);
  }, [bearerToken, parseTokenExp]);

  /**
   * 检查 Token 是否即将过期（1 分钟内）
   */
  const isTokenExpiringSoon = useCallback((): boolean => {
    const remaining = getTokenRemainingTime();
    return remaining > 0 && remaining < TOKEN_WARNING_THRESHOLD;
  }, [getTokenRemainingTime]);

  /**
   * 请求主站刷新 Token
   * 通过 postMessage 向父窗口（主站）发送刷新请求
   */
  const requestParentRefresh = useCallback((): void => {
    if (typeof window === "undefined") return;

    // 向主站请求新 Token
    const targetOrigin = resolvePostMessageTargetOrigin();
    if (!targetOrigin) return;

    window.parent.postMessage(
      {
        type: "LOTTERY_TOKEN_REFRESH_REQUEST",
        timestamp: Date.now(),
      },
      targetOrigin,
    );
  }, []);

  /**
   * 手动触发 Token 刷新
   */
  const refreshToken = useCallback(async (): Promise<void> => {
    if (retryCountRef.current >= MAX_RETRY) {
      setServerError(true, "Token 刷新失败，请返回主站重新进入");
      return;
    }

    clearServerError();
    retryCountRef.current++;

    // 向主站请求新 Token
    requestParentRefresh();

    // 等待主站响应（通过 postMessage）
    // 实际逻辑在下面的 useEffect 中处理
  }, [clearServerError, requestParentRefresh, setServerError]);

  /**
   * 监听主站 postMessage 发送的新 Token
   */
  useEffect(() => {
    if (typeof window === "undefined") return;

    void loadIframeAllowedOrigins();

    const handleMessage = async (event: MessageEvent): Promise<void> => {
      if (!isIframeOriginAllowed(event.origin)) {
        await loadIframeAllowedOrigins(true);
        if (!isIframeOriginAllowed(event.origin)) {
          console.warn("[TokenRefresh] Ignored message from unknown origin:", event.origin);
          return;
        }
      }

      const { data } = event;
      if (!data || typeof data !== "object") return;

      // 处理主站发送的新 Token（兼容 MAIN_REFRESH_TOKEN 与 LOTTERY_TOKEN_REFRESH_RESPONSE）
      if (
        (data.type === "LOTTERY_TOKEN_REFRESH_RESPONSE" || data.type === "MAIN_REFRESH_TOKEN") &&
        data.token
      ) {
        console.log("[TokenRefresh] Received new token from parent");
        setBearerToken(data.token);
        retryCountRef.current = 0; // 重置重试计数
      }

      // 处理主站通知 Token 即将过期
      if (data.type === "LOTTERY_TOKEN_EXPIRING_WARNING") {
        console.log("[TokenRefresh] Token expiring warning from parent");
        // 可以在这里显示提示或自动刷新
      }
    };

    window.addEventListener("message", handleMessage);
    return () => window.removeEventListener("message", handleMessage);
  }, [setBearerToken]);

  /**
   * 自动刷新逻辑
   */
  useEffect(() => {
    if (!bearerToken) {
      if (refreshTimerRef.current) {
        clearTimeout(refreshTimerRef.current);
        refreshTimerRef.current = null;
      }
      return;
    }

    const exp = parseTokenExp(bearerToken);
    if (!exp) return;

    const now = Date.now();
    const expMs = exp * 1000;
    const remaining = expMs - now;

    // 如果已经过期，立即请求刷新
    if (remaining <= 0) {
      console.warn("[TokenRefresh] Token already expired, requesting refresh");
      requestParentRefresh();
      return;
    }

    // 在过期前 30 秒刷新
    const refreshDelay = Math.max(0, remaining - TOKEN_WARNING_THRESHOLD);

    console.log(
      `[TokenRefresh] Token expires in ${Math.floor(remaining / 1000)}s, ` +
        `will refresh in ${Math.floor(refreshDelay / 1000)}s`,
    );

    refreshTimerRef.current = setTimeout(() => {
      console.log("[TokenRefresh] Auto-refreshing token");
      requestParentRefresh();
    }, refreshDelay);

    return () => {
      if (refreshTimerRef.current) {
        clearTimeout(refreshTimerRef.current);
      }
    };
  }, [bearerToken, parseTokenExp, requestParentRefresh]);

  return {
    refreshToken,
    getTokenRemainingTime,
    isTokenExpiringSoon,
  };
}
