/**
 * SSO 登录 hash 解析与 token 落地工具（v2.4 Entra ID OIDC）
 *
 * 事实源：docs/modules/organization/05-ui-interaction-spec.md「SSO 登录（v2.4）」
 * 配合：
 *   - frontend/src/app/(auth)/sso/landing/page.tsx（显式中间页）
 *   - frontend/src/components/common/AuthBootstrap.tsx（全局兜底 hash 处理）
 *
 * 共享逻辑：解析 location.hash 中的 accessToken / refreshToken，写
 * localStorage + zustand store，然后清掉 hash 防 referrer 泄漏。
 *
 * 后端 callback 成功时 302 到 `${sso_redirect}#accessToken=<jwt>&refreshToken=<jwt>`，
 * sso_redirect 是任意业务路径，所以本工具必须能在任何页面被调用、idempotent。
 */

import { useAuth } from '@/lib/auth';
import { normalizeRedirectTarget, DEFAULT_POST_LOGIN_PATH } from '@/lib/auth-redirect';

export type SsoLandingResult =
  | { kind: 'ok'; target: string }
  | { kind: 'noop' }
  | { kind: 'error'; errorCode: 'SSO_TOKEN_INVALID' };

/**
 * 从 hash 解析 accessToken / refreshToken。无 hash 或非 SSO hash 返回 null。
 */
function parseSsoHash(hash: string): { accessToken: string; refreshToken: string } | null {
  // hash 形如 #accessToken=xxx&refreshToken=yyy
  if (!hash || hash.length < 2) return null;
  const stripped = hash.startsWith('#') ? hash.slice(1) : hash;
  // 启发式：必须同时含 accessToken= 才进入 SSO 解析路径，避免误伤业务 hash（如 #section-1）
  if (!stripped.includes('accessToken=')) return null;

  const params = new URLSearchParams(stripped);
  const accessToken = params.get('accessToken') || '';
  const refreshToken = params.get('refreshToken') || '';
  if (!accessToken || !refreshToken) return null;
  return { accessToken, refreshToken };
}

/**
 * 安全跳转路径解析：优先 search 的 `?to=<path>`，回退当前 pathname+search，再回退 /overview。
 */
function resolveTarget(): string {
  if (typeof window === 'undefined') return DEFAULT_POST_LOGIN_PATH;
  const params = new URLSearchParams(window.location.search);
  const explicitTo = params.get('to');
  if (explicitTo) {
    return normalizeRedirectTarget(decodeURIComponent(explicitTo));
  }
  // 不带 ?to：跳转 sso_redirect 实际是浏览器当前 location（callback 已 302 到这里），
  // 直接保留 pathname+search 即可，避免空跳。
  const fallback = `${window.location.pathname}${window.location.search}`;
  return normalizeRedirectTarget(fallback);
}

/**
 * 主入口：解析 hash 并写入 token。
 *
 * 行为：
 *   - 无 hash 或 hash 不含 accessToken → 返回 `{ kind: 'noop' }`（非 SSO 回跳，不动）
 *   - hash 含 accessToken= 但解析失败（refresh 缺失/格式错） → `{ kind: 'error', errorCode: 'SSO_TOKEN_INVALID' }`
 *   - 成功 → 写 localStorage + zustand store + 清 hash → `{ kind: 'ok', target }`
 *
 * SSR safe：window 未定义直接返回 noop。
 */
export function applySsoTokensFromHash(): SsoLandingResult {
  if (typeof window === 'undefined') return { kind: 'noop' };

  const hash = window.location.hash;
  // 快速路径：完全没有 hash
  if (!hash || hash === '#') return { kind: 'noop' };

  // hash 中没有 accessToken= → 不是 SSO 回跳，不动业务 hash（如 #anchor）
  if (!hash.includes('accessToken=')) return { kind: 'noop' };

  const parsed = parseSsoHash(hash);
  if (!parsed) {
    // hash 含 accessToken= 但缺 refreshToken / 格式错 → 视为非法 SSO 回跳
    return { kind: 'error', errorCode: 'SSO_TOKEN_INVALID' };
  }

  // 1. 写 localStorage（key 与密码登录一致：token / refresh_token）
  try {
    localStorage.setItem('token', parsed.accessToken);
    localStorage.setItem('refresh_token', parsed.refreshToken);
  } catch (err) {
    // localStorage 写失败（隐私模式 / quota） → SSO 流程无法完成
    console.error('[sso-landing] localStorage write failed:', err);
    return { kind: 'error', errorCode: 'SSO_TOKEN_INVALID' };
  }

  // 2. 写 zustand store（state-only：token + isAuthenticated；user 由 reload() 后续拉 /users/me 填）
  //    注意：不调 useAuth.login()，因为它要求 user 对象，这里我们只有 token；
  //    user 由调用方 reload() 拉 /users/me 异步填上。
  try {
    useAuth.setState((prev) => ({
      ...prev,
      token: parsed.accessToken,
      isAuthenticated: true,
    }));
  } catch (err) {
    console.error('[sso-landing] zustand setState failed:', err);
  }

  // 3. 解析跳转目标
  const target = resolveTarget();

  // 4. 清掉 hash 防 token 通过 referrer / browser history 泄漏
  try {
    const cleanPath = `${window.location.pathname}${window.location.search}`;
    window.history.replaceState(null, '', cleanPath);
  } catch {
    /* noop */
  }

  return { kind: 'ok', target };
}
