// ticketExchange — обмен одноразового ticket на постоянный JWT.
//
// Поток:
//   rublox.pro / Майнкрафтия → POST /api-user/api/v1/auth/play-ticket → { ticket }
//   браузер открывает player.rublox.pro/<id>#ticket=<ticket>
//   плеер → POST /api-user/api/v1/auth/redeem-ticket { ticket } → { jwt, user }
//   плеер сохраняет JWT в localStorage["player_jwt"]
//
// На стороне нашего плеера здесь ТОЛЬКО redeem-сторона.
// Сторону play-ticket делают rublox.pro и Майнкрафтия (Этапы 5 и 6).

import axios from 'axios';
import { USER_addres } from '../api/API';

const JWT_KEY = 'player_jwt';

/**
 * Обменять ticket на JWT + user-данные.
 * Возвращает { jwt, user } или кидает ошибку (которую вызывающий ловит
 * и показывает в LoadingScreen).
 */
export async function redeemTicket(ticket) {
  const r = await axios.post(
    `${USER_addres}/api/v1/auth/redeem-ticket`,
    { ticket },
    { timeout: 15000 },
  );
  return r.data;
}

// «Зеркало» в Authorization — это ключ, который читают engine, скрипты
// уровней (game.save.*), KubikonBugReport, KubikonChatPanel и ещё ~10
// мест в скопированном 1-в-1 коде. Чтобы НЕ править engine (по правилу
// «1-в-1, ничего не ломать»), JWT кладётся в ОБА ключа:
//   - player_jwt: новый канон плеера (читают auth/PlayerAuth.jsx,
//     api/Kubikon3DService.js)
//   - Authorization: совместимость с Майнкрафтия-кодом из engine
//     (читают GameRuntime._saveBaseUrl, GdPlayerModeSkin, GdPlayerTrail,
//     GdPortalArch, KubikonChatPanel, KubikonComments, KubikonBugReport,
//     KubikonPlayer.jsx userId-getter и многое другое).
//
// Это разово при логине, читается из обоих мест — синхронизация
// гарантирована.
const AUTH_KEY_MIRROR = 'Authorization';

export function saveJWT(jwt) {
  try {
    localStorage.setItem(JWT_KEY, jwt);
    localStorage.setItem(AUTH_KEY_MIRROR, jwt);
  } catch (e) {}
}

export function getJWT() {
  try { return localStorage.getItem(JWT_KEY); } catch (e) { return null; }
}

export function clearJWT() {
  try {
    localStorage.removeItem(JWT_KEY);
    localStorage.removeItem(AUTH_KEY_MIRROR);
  } catch (e) {}
}

/**
 * Достать ticket из window.location.hash. Возвращает hex-строку или null.
 * Hash чистится отдельно (после успешного redeem) через history.replaceState,
 * чтобы юзер не мог поделиться URL с одноразовым ticket'ом (даже после
 * его сжигания это просто плохой UX).
 */
export function readTicketFromHash() {
  if (typeof window === 'undefined') return null;
  const m = /(?:^|[#&])ticket=([0-9a-fA-F]+)/.exec(window.location.hash || '');
  return m ? m[1] : null;
}

/**
 * Достать team_jwt из window.location.hash. Используется когда модератор
 * с team.rublox.pro открывает draft/review-игру в плеере для проверки.
 *
 * Поток: team-фронт берёт свой team_jwt из localStorage и формирует
 * URL вида `https://player.rublox.pro/<id>#team_jwt=<jwt>`. Мы кладём
 * этот jwt прямо в localStorage плеера (без redeem-flow) — team_jwt и
 * user_jwt подписаны одним секретом, user-сервис их обрабатывает
 * одинаково. На стороне storys get_project ищет moderator-роль через
 * team-flask (см. team_mod_auth.py) и пропускает к draft/review-проектам.
 *
 * Безопасность: team_jwt и так уже выдаётся модератору после входа в
 * team.rublox.pro; передача его в hash другому поддомену того же origin
 * (rublox.pro) не повышает риск. Hash не уходит в логи серверов.
 */
export function readTeamJwtFromHash() {
  if (typeof window === 'undefined') return null;
  // JWT-формат: header.payload.signature — три blob'а из base64url, точки.
  const m = /(?:^|[#&])team_jwt=([A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+)/
    .exec(window.location.hash || '');
  return m ? m[1] : null;
}

export function clearTicketFromUrl() {
  if (typeof window === 'undefined' || !window.history?.replaceState) return;
  try {
    window.history.replaceState(null, '', window.location.pathname + window.location.search);
  } catch (e) {}
}
