export type CollaborationRoomDescriptor = {
  roomId: string;
  secret: string;
  projectId: string;
};

const ROOM_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;
const SECRET_RE = /^[0-9a-f]{64}$/iu;
const PROJECT_ID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/iu;

function randomHex(bytesLength: number): string {
  const bytes = crypto.getRandomValues(new Uint8Array(bytesLength));
  return Array.from(bytes, (value) => value.toString(16).padStart(2, '0')).join('');
}

export function createCollaborationRoomDescriptor(projectId: string): CollaborationRoomDescriptor {
  if (!PROJECT_ID_RE.test(projectId.trim())) throw new Error('A registered Learnitive project is required for collaboration');
  return { roomId: crypto.randomUUID(), secret: randomHex(32), projectId: projectId.trim().toLowerCase() };
}

export function isValidCollaborationRoomId(value: string): boolean {
  return ROOM_ID_RE.test(value.trim());
}

export function isValidCollaborationSecret(value: string): boolean {
  return SECRET_RE.test(value.trim());
}

export function buildCollaborationJoinUrl(
  descriptor: CollaborationRoomDescriptor,
  origin = typeof window === 'undefined' ? 'https://www.learnitive.com' : window.location.origin,
): string {
  if (!isValidCollaborationRoomId(descriptor.roomId) || !isValidCollaborationSecret(descriptor.secret)) {
    throw new Error('Invalid TX7 collaboration descriptor');
  }
  if (!PROJECT_ID_RE.test(descriptor.projectId)) throw new Error('Invalid collaboration project identity');
  return `${origin.replace(/\/$/u, '')}/join/${encodeURIComponent(descriptor.roomId)}/${encodeURIComponent(descriptor.projectId)}#${descriptor.secret}`;
}

export function parseCollaborationJoinLocation(input: {
  pathname: string;
  hash: string;
}): CollaborationRoomDescriptor | undefined {
  const match = /^\/join\/([^/]+)\/([^/]+)\/?$/u.exec(input.pathname);
  if (!match) return undefined;
  const roomId = decodeURIComponent(match[1] ?? '').trim();
  const projectId = decodeURIComponent(match[2] ?? '').trim().toLowerCase();
  const secret = input.hash.replace(/^#/u, '').trim();
  if (!isValidCollaborationRoomId(roomId) || !isValidCollaborationSecret(secret) || !PROJECT_ID_RE.test(projectId)) return undefined;
  return { roomId, secret, projectId };
}
