// ATProto TID: 53-bit microsecond timestamp + 10-bit random clock ID, s-base32 encoded.
// Equivalent to TID.nextStr() from @atproto/common without the Node.js dependency.
const BASE32 = '234567abcdefghijklmnopqrstuvwxyz'
export function nextTid(): string {
  const us = BigInt(Date.now()) * 1000n
  const clk = BigInt(Math.floor(Math.random() * 1024))
  let n = (us << 10n) | clk
  let s = ''
  for (let i = 0; i < 13; i++) {
    s = BASE32[Number(n & 31n)] + s
    n >>= 5n
  }
  return s
}

export async function resolveHandle(handle: string): Promise<string> {
  const res = await fetch(
    `https://bsky.social/xrpc/com.atproto.identity.resolveHandle?handle=${encodeURIComponent(handle)}`,
  )
  if (!res.ok) throw new Error(`Could not resolve handle (${res.status})`)
  const { did } = (await res.json()) as { did: string }
  return did
}

// Accepts a DID (did:plc:… or did:web:…) or a handle (with or without leading @).
// Always returns a DID.
export async function resolveDid(handleOrDid: string): Promise<string> {
  if (handleOrDid.startsWith('did:')) return handleOrDid
  const handle = handleOrDid.startsWith('@') ? handleOrDid.slice(1) : handleOrDid
  return resolveHandle(handle)
}

export async function resolvePdsUrl(did: string): Promise<string> {
  const docUrl = did.startsWith('did:plc:')
    ? `https://plc.directory/${did}`
    : `https://${did.slice('did:web:'.length)}/.well-known/did.json`
  const res = await fetch(docUrl)
  if (!res.ok) throw new Error(`DID resolution failed (${res.status})`)
  const doc = (await res.json()) as {
    service?: Array<{ id: string; type: string; serviceEndpoint: string }>
  }
  const pds = doc.service?.find((s) => s.type === 'AtprotoPersonalDataServer')?.serviceEndpoint
  if (!pds) throw new Error('Could not find PDS in DID document')
  return pds
}
