import { type LoaderFunctionArgs, redirect } from "@remix-run/node";
import { useEffect } from "react";
import { useSearchParams } from "@remix-run/react";
import { createUserSession, sessionStorage } from "~/api/login/auth.server";
import { OAuthClient } from "~/api/login/oauth-client";
import { getServerOAuthConfigRuntime, getPortOAuthConfig } from "~/config/oauth-secret.server";
import { loginWithOAuth, type LoginRequest } from "~/api/login/login-client";
import { isMobileDevice, MOBILE_CHAT_PATH } from "~/utils/mobile-detect.server";

/**
 * 端口号到地区的映射关系
 * 根据 ecosystem.config.cjs 配置文件
 */
const PORT_TO_AREA_MAP: Record<string, string> = {
  '51703': '梅州',
  '51704': '云浮',
  '51705': '揭阳',
  '51706': '潮州',
  '51707': '省局'
};

/**
 * 根据端口号获取地区
 * @param port - 端口号
 * @returns 地区名称，如果未找到则返回 undefined
 */
function getAreaByPort(port: string): string | undefined {
  return PORT_TO_AREA_MAP[port];
}

/**
 * 辅助函数：使用 session flash 重定向到登录页面并传递错误信息
 */
async function redirectToLoginWithError(request: Request, errorMessage: string) {
  const session = await sessionStorage.getSession(request.headers.get("Cookie"));
  session.flash("loginError", errorMessage);

  return redirect("/login", {
    headers: {
      "Set-Cookie": await sessionStorage.commitSession(session)
    }
  });
}

export async function loader({ request }: LoaderFunctionArgs) {
  const url = new URL(request.url);
  // const origin = url.origin; // 获取请求的源 (e.g., "http://10.79.97.17:51703")
  const port = url.port; // 获取端口号
  const area = getAreaByPort(port); // 根据端口号获取地区
  const code = url.searchParams.get("code");
  const state = url.searchParams.get("state");
  const error = url.searchParams.get("error");
  const error_description = url.searchParams.get("error_description");

  // 🔑 检查是否是管理员账密登录（直接传递 token 和 userInfo）
  const token = url.searchParams.get("token");
  const userInfo = url.searchParams.get("userInfo");
  // const redirectTo = url.searchParams.get("redirectTo") || "/";

  // 🔑 如果有 token 和 userInfo，说明是管理员账密登录
  // login.tsx action 已经创建了 Cookie Session，这里只需要返回 null
  // 让客户端组件从 URL 读取 token 并保存到 localStorage
  if (token && userInfo) {
    console.log("✅ [Callback] 检测到管理员账密登录，交给客户端处理");

    // 验证 userInfo 格式（防止解析错误）
    try {
      JSON.parse(decodeURIComponent(userInfo));
    } catch (error) {
      console.error("❌ [Callback] 解析管理员登录用户信息失败:", error);
      return redirectToLoginWithError(request, "登录失败：用户信息格式错误");
    }

    // ✅ 直接返回 null，让客户端 useEffect 处理
    // 注意：Cookie Session 已经在 login.tsx action 中通过 createUserSession 创建
    return null;
  }

  // console.log("🔧 OAuth2.0回调参数:", {
  //   code: code ? `${code.substring(0, 10)}...` : null,
  //   state: state,
  //   error: error,
  //   error_description: error_description,
  //   fullUrl: request.url,
  //   port: port,
  //   area: area
  // });

  // 检查是否有错误
  if (error) {
    console.error("❌ OAuth2.0授权失败:", error, error_description);
    return redirectToLoginWithError(request, error_description || error || "授权失败");
  }

  // 检查是否有授权码
  if (!code) {
    console.error("❌ OAuth2.0回调缺少授权码");
    return redirectToLoginWithError(request, "登录过程中缺少授权码，请重新登录");
  }

  // 验证状态值
  if (!state || !state.endsWith("_idp")) {
    console.error("❌ OAuth2.0状态值验证失败:", { state, expectedSuffix: "_idp" });
    return redirectToLoginWithError(request, "登录状态验证失败，请重新登录");
  }

  console.log("✅ OAuth2.0回调参数验证通过");

  // 🔑 判断是否从钉钉登录：检查 remote-user header
  const remoteUser = request.headers.get("remote-user");
  const isDingTalkLogin = remoteUser !== null;

  console.log("🔧 [Callback] remote-user 检测:", {
    remoteUser: remoteUser,
    isDingTalkLogin: isDingTalkLogin,
    loginType: isDingTalkLogin ? '钉钉Web登录' : '内网Web登录'
  });

  // 声明在 try 外部，以便在 catch 中访问
  let tokenResponse = null;

  // 获取端口特定的OAuth配置（包含钉钉回调地址）
  const portOAuthConfig = getPortOAuthConfig(port);
  const oauthClient = new OAuthClient(portOAuthConfig);

  // 🔑 根据登录类型设置回调地址
  if (isDingTalkLogin) {
    // 钉钉登录：使用钉钉回调地址
    if (portOAuthConfig.dingtalkRedirectUri) {
      oauthClient.setRedirectUri(portOAuthConfig.dingtalkRedirectUri);
      console.log("🔧 [Callback] 使用钉钉回调地址:", portOAuthConfig.dingtalkRedirectUri);
    } else {
      console.warn("⚠️ [Callback] 钉钉登录但未配置钉钉回调地址，使用默认内网地址");
    }
  } else {
    // 内网登录：使用默认内网回调地址
    console.log("🔧 [Callback] 使用内网回调地址:", portOAuthConfig.redirectUri);
  }

  try {
    console.log("🔧 开始处理OAuth2.0回调");

    // 开始获取访问令牌
    tokenResponse = await oauthClient.getAccessToken(code);
    if (!tokenResponse) {
      console.error("获取访问令牌失败");
      // 注意：此时还没有 access_token，无法调用 IDaaS 登出
      // 只能重定向到登录页，让用户重新开始登录流程
      return redirectToLoginWithError(request, "获取访问令牌失败，请重试");
    }
    console.log("✅ [Callback] 访问令牌获取成功");


    const userInfo = await oauthClient.getUserInfo(tokenResponse.access_token);
    if(!userInfo || !userInfo.success){
      console.error('获取用户信息失败：',userInfo);

      // 🔑 关键：此时 IDaaS 那边已经登录成功，但我们获取用户信息失败
      // 需要调用 IDaaS 登出，清除 IDaaS 的登录状态，避免用户下次登录时出现问题
      try {
        const logoutUrl = `${url.protocol}//${url.host}/login`;
        const logoutSuccess = await oauthClient.logout(tokenResponse.access_token, logoutUrl);
        if (logoutSuccess) {
          console.log("✅ [Callback] 已清除 IDaaS 登录状态");
        } else {
          console.warn("⚠️ [Callback] 清除 IDaaS 登录状态失败");
        }
      } catch (logoutError) {
        console.error("❌ [Callback] 调用 IDaaS 登出时出错:", logoutError);
      }

      return redirectToLoginWithError(request, "获取用户信息失败，请重试");
    }
    console.log("✅ [Callback] 用户信息获取成功");

    // 🔑 检测移动端设备，决定重定向目标
    const isMobile = isMobileDevice(request);
    console.log(`📱 [Callback] 设备类型检测: ${isMobile ? '移动端' : '桌面端'}`);

    // 移动端用户直接跳转到对话页面，桌面端用户跳转到首页选择模块
    const redirectTo = isMobile ? MOBILE_CHAT_PATH : "/";

    // 调用后端登录接口,传递 OAuth 用户信息,获取 JWT token
    const loginRequest: LoginRequest = {
      userInfo: userInfo.data,
      expiresIn: tokenResponse.expires_in,
      area: area
    };

    const loginResponse = await loginWithOAuth(loginRequest);

    if (!loginResponse.success || !loginResponse.data) {
      console.error("❌ [Callback] 后端登录失败:", loginResponse.error);

      // 🔑 登录失败，需要清除 IDaaS 登录状态
      try {
        const logoutUrl = `${url.protocol}//${url.host}/login`;
        const logoutSuccess = await oauthClient.logout(tokenResponse.access_token, logoutUrl);
        if (logoutSuccess) {
          console.log("✅ [Callback] 已清除 IDaaS 登录状态（后端登录失败）");
        } else {
          console.warn("⚠️ [Callback] 清除 IDaaS 登录状态失败（后端登录失败）");
        }
      } catch (logoutError) {
        console.error("❌ [Callback] 调用 IDaaS 登出时出错（后端登录失败）:", logoutError);
      }

      return redirectToLoginWithError(request, loginResponse.error || "登录失败，请重新登录");
    }

    console.log("✅ [Callback] 后端登录成功，JWT token 已获取");
    const frontendJWT = loginResponse.data.access_token;
    const savedUserInfo = loginResponse.data.user_info;
    const backExpiresIn = loginResponse.data.expires_in || (60 * 60 * 8)

    // 🔑 提取后端返回的签发时间并转换为时间戳
    let tokenIssuedAt = Date.now(); // 默认使用当前时间
    if (loginResponse.data.issued_time) {
      try {
        // 后端返回格式："2025-11-18 17:41:06"
        // 转换为时间戳（毫秒）
        tokenIssuedAt = new Date(loginResponse.data.issued_time.replace(' ', 'T')).getTime();
        console.log("📅 [Callback] 使用后端返回的签发时间:", loginResponse.data.issued_time, "→", tokenIssuedAt);
      } catch (error) {
        console.warn("⚠️ [Callback] 无法解析 issued_time，使用当前时间:", error);
      }
    }

    // 更新userInfo以包含数据库ID、JWT（user_role 从后端返回）
    const enhancedUserInfo = {
      ...userInfo.data, // 保留OAuth返回的原字段（包含 nickname 等）
      username: savedUserInfo.username,
      nick_name: savedUserInfo.nick_name,
      phone_number: savedUserInfo.phone_number,
      email: savedUserInfo.email,
      ou_id: savedUserInfo.ou_id,
      ou_name: savedUserInfo.ou_name,
      is_leader: savedUserInfo.is_leader,
      user_id: savedUserInfo.user_id,
      user_role: savedUserInfo.user_role, // 使用后端返回的角色
      area: savedUserInfo.area,  // 🔑 用户所属地区
      frontend_jwt: frontendJWT,
      // 🔑 包含后端返回的组织信息字段（可能为null）
      tenant_name: savedUserInfo.tenant_name,
      dep_name: savedUserInfo.dep_name,
      dep_short_name: savedUserInfo.dep_short_name,
    };

    // 🔑 重要：将 token 和用户信息作为 URL 参数传递给客户端
    // 客户端 useEffect 会将其保存到 localStorage
    const callbackUrl = new URL('/callback', url.origin);
    callbackUrl.searchParams.set('token', frontendJWT);
    callbackUrl.searchParams.set('userInfo', encodeURIComponent(JSON.stringify({
      user_id: savedUserInfo.user_id,
      username: savedUserInfo.username,
      nick_name: savedUserInfo.nick_name,
      email: savedUserInfo.email,
      phone_number: savedUserInfo.phone_number,
      ou_id: savedUserInfo.ou_id,
      ou_name: savedUserInfo.ou_name,
      is_leader: savedUserInfo.is_leader,
      user_role: savedUserInfo.user_role,
      area: savedUserInfo.area,  // 🔑 用户所属地区
      sub: userInfo.data.sub,
      // 🔑 包含后端返回的组织信息字段（可能为null）
      tenant_name: savedUserInfo.tenant_name,
      dep_name: savedUserInfo.dep_name,
      dep_short_name: savedUserInfo.dep_short_name,
    })));
    callbackUrl.searchParams.set('redirectTo', redirectTo);

    // 使用统一的session创建函数
    return createUserSession({
      isAuthenticated: true,
      userRole: savedUserInfo.user_role, // 使用后端返回的角色
      redirectTo: callbackUrl.toString(), // 先跳转到 callback 页面保存 token
      accessToken: tokenResponse.access_token,
      refreshToken: tokenResponse.refresh_token,
      tokenExpiresIn: backExpiresIn,
      tokenIssuedAt: tokenIssuedAt,       // 🔑 传递后端返回的签发时间
      userInfo: enhancedUserInfo,
      frontendJWT
    });

  } catch (error) {
    console.error("OAuth2.0回调处理失败:", error);

    // 🔑 如果已经获取到了 access_token，需要清除 IDaaS 登录状态
    if (tokenResponse?.access_token) {
      try {
        const logoutUrl = `${url.protocol}//${url.host}/login`;
        const logoutSuccess = await oauthClient.logout(tokenResponse.access_token, logoutUrl);
        if (logoutSuccess) {
          console.log("✅ [Callback] 已清除 IDaaS 登录状态（回调处理异常）");
        } else {
          console.warn("⚠️ [Callback] 清除 IDaaS 登录状态失败（回调处理异常）");
        }
      } catch (logoutError) {
        console.error("❌ [Callback] 调用 IDaaS 登出时出错（回调处理异常）:", logoutError);
      }
    }

    return redirectToLoginWithError(request, "登录回调处理失败，请重新登录");
  }
}

export default function Callback() {
  const [searchParams] = useSearchParams();

  useEffect(() => {
    // 从 URL 参数中获取 token（如果有）
    const token = searchParams.get("token");
    const userInfo = searchParams.get("userInfo");
    // 从 URL 参数中获取重定向目标（服务端已根据设备类型设置）
    const redirectTo = searchParams.get("redirectTo") || "/";

    if (token && typeof window !== 'undefined') {
      console.log('🔑 [Callback] 开始保存 token 到 localStorage');

      // 存储 token 到 localStorage
      localStorage.setItem('access_token', token);
      console.log('✅ [Callback] Token 已存储到 localStorage');

      // 存储用户信息
      if (userInfo) {
        try {
          const parsedUserInfo = JSON.parse(decodeURIComponent(userInfo));
          localStorage.setItem('user_info', JSON.stringify(parsedUserInfo));
          console.log('✅ [Callback] 用户信息已存储到 localStorage:', parsedUserInfo);
        } catch (error) {
          console.error('❌ [Callback] 解析用户信息失败:', error);
        }
      }

      // ⏱️ 短暂延迟后跳转，确保 localStorage 写入完成
      // 使用 requestAnimationFrame 确保 DOM 更新后立即跳转
      requestAnimationFrame(() => {
        setTimeout(() => {
          console.log(`🚀 [Callback] 跳转到目标页面: ${redirectTo}`);
          window.location.href = redirectTo;
        }, 100); // 减少延迟从 500ms 到 100ms
      });
    }
  }, [searchParams]);

  return (
    <div className="flex items-center justify-center min-h-screen">
      <div className="text-center">
        <div className="animate-spin rounded-full h-12 w-12 border-b-2 border-blue-500 mx-auto"></div>
        <p className="mt-4 text-gray-600">正在处理登录...</p>
        <p className="mt-2 text-sm text-gray-500">即将跳转...</p>
      </div>
    </div>
  );
}