/**
 * 인증 이벤트 로거
 * - 토큰 갱신/삭제/리다이렉트 발생 시 원인을 기록
 * - localStorage에 저장하여 브라우저에서 확인 가능
 * - 콘솔에서 window.__AUTH_LOG.show() 로 조회
 */

const STORAGE_KEY = "auth_debug_log";
const MAX_ENTRIES = 200;

export type AuthEventType =
  | "TOKEN_SET"
  | "TOKEN_REMOVED"
  | "TOKEN_EXPIRED_DETECTED"
  | "TOKEN_REFRESH_START"
  | "TOKEN_REFRESH_SUCCESS"
  | "TOKEN_REFRESH_FAIL"
  | "REDIRECT_TO_LOGIN"
  | "API_401_RECEIVED"
  | "API_401_RETRY"
  | "AUTH_CHECK_START"
  | "AUTH_CHECK_SUCCESS"
  | "AUTH_CHECK_FAIL"
  | "AUTH_GUARD_BLOCK"
  | "AUTH_GUARD_PASS"
  | "MENU_LOAD_FAIL"
  | "VISIBILITY_CHANGE"
  | "MIDDLEWARE_REDIRECT";

interface AuthLogEntry {
  timestamp: string;
  event: AuthEventType;
  detail: string;
  tokenStatus: string;
  url: string;
  stack?: string;
}

function getTokenSummary(): string {
  if (typeof window === "undefined") return "SSR";

  const token = localStorage.getItem("authToken");
  if (!token) return "없음";

  try {
    const payload = JSON.parse(atob(token.split(".")[1]));
    const exp = payload.exp * 1000;
    const now = Date.now();
    const remainMs = exp - now;

    if (remainMs <= 0) {
      return `만료됨(${Math.abs(Math.round(remainMs / 60000))}분 전)`;
    }

    const remainMin = Math.round(remainMs / 60000);
    const remainHour = Math.floor(remainMin / 60);
    const min = remainMin % 60;

    return `유효(${remainHour}h${min}m 남음, user:${payload.userId})`;
  } catch {
    return "파싱실패";
  }
}

function getCallStack(): string {
  try {
    const stack = new Error().stack || "";
    const lines = stack.split("\n").slice(3, 7);
    return lines.map((l) => l.trim()).join(" <- ");
  } catch {
    return "";
  }
}

function writeLog(event: AuthEventType, detail: string) {
  if (typeof window === "undefined") return;

  const entry: AuthLogEntry = {
    timestamp: new Date().toISOString(),
    event,
    detail,
    tokenStatus: getTokenSummary(),
    url: window.location.pathname + window.location.search,
    stack: getCallStack(),
  };

  // 콘솔 출력 (그룹)
  const isError = ["TOKEN_REMOVED", "REDIRECT_TO_LOGIN", "API_401_RECEIVED", "TOKEN_REFRESH_FAIL", "AUTH_GUARD_BLOCK"].includes(event);
  const logFn = isError ? console.warn : console.debug;
  logFn(`[AuthLog] ${event}: ${detail} | 토큰: ${entry.tokenStatus} | ${entry.url}`);

  // localStorage에 저장
  try {
    const stored = localStorage.getItem(STORAGE_KEY);
    const logs: AuthLogEntry[] = stored ? JSON.parse(stored) : [];
    logs.push(entry);

    // 최대 개수 초과 시 오래된 것 제거
    while (logs.length > MAX_ENTRIES) {
      logs.shift();
    }

    localStorage.setItem(STORAGE_KEY, JSON.stringify(logs));
  } catch {
    // localStorage 공간 부족 등의 경우 무시
  }
}

/**
 * 저장된 로그 조회
 */
function getLogs(): AuthLogEntry[] {
  if (typeof window === "undefined") return [];
  try {
    const stored = localStorage.getItem(STORAGE_KEY);
    return stored ? JSON.parse(stored) : [];
  } catch {
    return [];
  }
}

/**
 * 로그 초기화
 */
function clearLogs() {
  if (typeof window === "undefined") return;
  localStorage.removeItem(STORAGE_KEY);
}

/**
 * 로그를 테이블 형태로 콘솔에 출력
 */
function showLogs(filter?: AuthEventType | "ERROR") {
  const logs = getLogs();

  if (logs.length === 0) {
    console.log("[AuthLog] 저장된 로그가 없습니다.");
    return;
  }

  let filtered = logs;
  if (filter === "ERROR") {
    filtered = logs.filter((l) =>
      ["TOKEN_REMOVED", "REDIRECT_TO_LOGIN", "API_401_RECEIVED", "TOKEN_REFRESH_FAIL", "AUTH_GUARD_BLOCK", "AUTH_CHECK_FAIL", "TOKEN_EXPIRED_DETECTED"].includes(l.event)
    );
  } else if (filter) {
    filtered = logs.filter((l) => l.event === filter);
  }

  console.log(`\n[AuthLog] 총 ${filtered.length}건 (전체 ${logs.length}건)`);
  console.log("─".repeat(120));

  filtered.forEach((entry, i) => {
    const time = entry.timestamp.replace("T", " ").split(".")[0];
    console.log(
      `${i + 1}. [${time}] ${entry.event}\n   상세: ${entry.detail}\n   토큰: ${entry.tokenStatus}\n   경로: ${entry.url}${entry.stack ? `\n   호출: ${entry.stack}` : ""}\n`
    );
  });
}

/**
 * 마지막 리다이렉트 원인 조회
 */
function getLastRedirectReason(): AuthLogEntry | null {
  const logs = getLogs();
  for (let i = logs.length - 1; i >= 0; i--) {
    if (logs[i].event === "REDIRECT_TO_LOGIN") {
      return logs[i];
    }
  }
  return null;
}

/**
 * 로그를 텍스트 파일로 다운로드
 */
function downloadLogs() {
  if (typeof window === "undefined") return;

  const logs = getLogs();
  if (logs.length === 0) {
    console.log("[AuthLog] 저장된 로그가 없습니다.");
    return;
  }

  const text = logs
    .map((entry, i) => {
      const time = entry.timestamp.replace("T", " ").split(".")[0];
      return `[${i + 1}] ${time} | ${entry.event}\n    상세: ${entry.detail}\n    토큰: ${entry.tokenStatus}\n    경로: ${entry.url}${entry.stack ? `\n    호출: ${entry.stack}` : ""}`;
    })
    .join("\n\n");

  const blob = new Blob([text], { type: "text/plain;charset=utf-8" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `auth-debug-log_${new Date().toISOString().slice(0, 19).replace(/[T:]/g, "-")}.txt`;
  a.click();
  URL.revokeObjectURL(url);

  console.log("[AuthLog] 로그 파일 다운로드 완료");
}

// 전역 접근 가능하게 등록
if (typeof window !== "undefined") {
  (window as any).__AUTH_LOG = {
    show: showLogs,
    errors: () => showLogs("ERROR"),
    clear: clearLogs,
    download: downloadLogs,
    lastRedirect: getLastRedirectReason,
    raw: getLogs,
  };
}

export const AuthLogger = {
  log: writeLog,
  getLogs,
  clearLogs,
  showLogs,
  downloadLogs,
  getLastRedirectReason,
};

export default AuthLogger;
