"use client";

import { useEffect, useCallback, type ReactNode } from "react";

import { usePlayerSessionStore } from "@/stores/player-session-store";
import { setPlayerBearerToken } from "@/lib/lottery-auth";
import {
  loadIframeAllowedOrigins,
  messageToken,
  resolvePostMessageTargetOrigin,
  resolveTrustedParentMessage,
} from "@/lib/iframe-origins";

function sanitizeUrlForParent(href: string): string {
  try {
    const url = new URL(href);
    url.searchParams.delete("token");
    return `${url.pathname}${url.search}${url.hash}`;
  } catch {
    return href;
  }
}

function resolveSafeInAppPath(path: string): string | null {
  if (!path.startsWith("/") || path.startsWith("//")) {
    return null;
  }

  try {
    const url = new URL(path, window.location.origin);
    if (url.origin !== window.location.origin) {
      return null;
    }

    return `${url.pathname}${url.search}${url.hash}`;
  } catch {
    return null;
  }
}

/**
 * iframe 通信桥接组件
 *
 * 功能：
 * 1. 监听父窗口（主站）通过 postMessage 发送的 Token
 * 2. 向父窗口发送心跳和状态通知
 * 3. 支持在主站 iframe 内嵌入时的双向通信
 */
export function IframeBridge({ children }: { children: ReactNode }): ReactNode {
  const setBearerToken = usePlayerSessionStore((state) => state.setBearerToken);

  /**
   * 向父窗口发送消息
   */
  const sendToParent = useCallback(
    (type: string, payload?: Record<string, unknown>): void => {
      if (typeof window === "undefined" || window.parent === window) return;

      const targetOrigin = resolvePostMessageTargetOrigin();
      if (!targetOrigin) return;

      window.parent.postMessage(
        {
          type: `LOTTERY_${type}`,
          payload,
          timestamp: Date.now(),
          source: "lottery-iframe",
        },
        targetOrigin,
      );
    },
    [],
  );

  /**
   * 通知父窗口：已准备就绪
   */
  const notifyReady = useCallback((): void => {
    sendToParent("READY", {
      url: sanitizeUrlForParent(window.location.href),
      userAgent: navigator.userAgent,
    });
  }, [sendToParent]);

  /**
   * 通知父窗口：需要新 Token
   */
  const notifyTokenNeeded = useCallback((): void => {
    sendToParent("TOKEN_NEEDED", {
      reason: "token_expired",
    });
  }, [sendToParent]);

  /**
   * 通知父窗口：Token 刷新成功
   */
  const notifyTokenRefreshed = useCallback((): void => {
    sendToParent("TOKEN_REFRESHED");
  }, [sendToParent]);

  /**
   * 通知父窗口：发生错误
   */
  const notifyError = useCallback(
    (error: string): void => {
      sendToParent("ERROR", { error });
    },
    [sendToParent],
  );

  /**
   * 监听父窗口消息
   */
  useEffect(() => {
    if (typeof window === "undefined") return;

    // 检查是否在 iframe 内
    const isInIframe = window.self !== window.top;
    if (!isInIframe) {
      console.log("[IframeBridge] Not in iframe, skipping bridge setup");
      return;
    }

    console.log("[IframeBridge] Setting up iframe communication");

    const handleMessage = async (event: MessageEvent): Promise<void> => {
      const data = await resolveTrustedParentMessage(event);
      if (data === null) {
        console.warn("[IframeBridge] Rejected untrusted parent message from:", event.origin);
        return;
      }

      console.log("[IframeBridge] Received message:", data.type);

      switch (data.type) {
        // 主站发送初始化 Token
        case "MAIN_INIT_TOKEN": {
          const token = messageToken(data);
          if (token !== null) {
            console.log("[IframeBridge] Received initial token");
            setBearerToken(token);
            setPlayerBearerToken(token);
            // 勿再 notifyReady()，否则主站会重复 MAIN_INIT_TOKEN 导致消息刷屏
          }
          break;
        }

        // 主站刷新 Token
        case "MAIN_REFRESH_TOKEN": {
          const token = messageToken(data);
          if (token !== null) {
            console.log("[IframeBridge] Received refreshed token");
            setBearerToken(token);
            setPlayerBearerToken(token);
            notifyTokenRefreshed();
          }
          break;
        }

        // 主站通知 Token 即将过期
        case "MAIN_TOKEN_EXPIRING":
          console.log("[IframeBridge] Token expiring soon");
          // 可以显示提示或自动刷新
          break;

        // 主站请求当前状态
        case "MAIN_REQUEST_STATUS":
          sendToParent("STATUS_RESPONSE", {
            isReady: true,
            currentPath: window.location.pathname,
          });
          break;

        // 主站导航请求
        case "MAIN_NAVIGATE":
          if (typeof data.path === "string") {
            const nextPath = resolveSafeInAppPath(data.path);
            if (nextPath) {
              window.history.pushState({}, "", nextPath);
            }
          }
          break;

        default:
          break;
      }
    };

    window.addEventListener("message", handleMessage);

    // 先加载后台白名单，再发送 READY，避免父站立即回 Token 时被本端误拒。
    void loadIframeAllowedOrigins().finally(() => {
      notifyReady();
    });

    const originsRefresh = setInterval(() => {
      void loadIframeAllowedOrigins(true);
    }, 60_000);

    // 定期发送心跳
    const heartbeat = setInterval(() => {
      sendToParent("HEARTBEAT", {
        timestamp: Date.now(),
      });
    }, 30000); // 每 30 秒

    return () => {
      window.removeEventListener("message", handleMessage);
      clearInterval(originsRefresh);
      clearInterval(heartbeat);
    };
  }, [notifyReady, notifyTokenRefreshed, sendToParent, setBearerToken]);

  // 暴露全局方法供调试
  useEffect(() => {
    if (typeof window === "undefined") return;

    (window as unknown as Record<string, unknown>).lotteryIframeBridge = {
      notifyReady,
      notifyTokenNeeded,
      notifyError,
      sendToParent,
    };
  }, [notifyError, notifyReady, notifyTokenNeeded, sendToParent]);

  return children;
}

/**
 * 检测当前是否在 iframe 内
 */
export function isInIframe(): boolean {
  if (typeof window === "undefined") return false;
  try {
    return window.self !== window.top;
  } catch {
    return true; // 跨域时无法访问 window.top，说明在 iframe 内
  }
}

/**
 * 获取父窗口信息
 */
export function getParentInfo(): {
  isInIframe: boolean;
  referrer: string;
} {
  if (typeof window === "undefined") {
    return { isInIframe: false, referrer: "" };
  }

  return {
    isInIframe: isInIframe(),
    referrer: document.referrer || "",
  };
}
