import type { AuthSession, JwtPayload, MeResponse } from '../../types/auth'

const apiBaseUrl = import.meta.env.VITE_API_URL ?? 'http://localhost:5000'

function parseJwtPayload(token: string): JwtPayload | null {
  try {
    const [, payload] = token.split('.')

    if (!payload) {
      return null
    }

    const normalized = payload.replace(/-/g, '+').replace(/_/g, '/')
    const json = globalThis.atob(normalized)
    return JSON.parse(json) as JwtPayload
  } catch {
    return null
  }
}

function getSessionFromToken(token: string): AuthSession | null {
  const payload = parseJwtPayload(token)

  if (!payload?.exp) {
    return null
  }

  const expiresAtUtc = new Date(payload.exp * 1000)

  if (expiresAtUtc.getTime() <= Date.now()) {
    return null
  }

  return {
    token,
    userId: payload.sub ? Number(payload.sub) : null,
    username: payload.unique_name ?? payload.name ?? 'User',
    expiresAtUtc: expiresAtUtc.toISOString(),
    isAdmin: payload.role === 'Admin',
  }
}

export async function fetchValidatedSession(
  token: string,
): Promise<AuthSession | null> {
  const baseSession = getSessionFromToken(token)

  if (!baseSession) {
    return null
  }

  try {
    const response = await fetch(`${apiBaseUrl}/api/user/me`, {
      credentials: 'include',
      headers: { Authorization: `Bearer ${token}` },
    })

    if (!response.ok) {
      return null
    }

    const me = (await response.json()) as MeResponse

    return {
      token,
      userId: me.id,
      username: me.username,
      expiresAtUtc: baseSession.expiresAtUtc,
      isAdmin: baseSession.isAdmin,
    }
  } catch {
    return null
  }
}

export async function loginWithCredentials(
  username: string,
  password: string,
): Promise<{ token: string }> {
  const response = await fetch(`${apiBaseUrl}/api/user/login`, {
    method: 'POST',
    credentials: 'include',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, password }),
  })

  const data = (await response.json()) as
    | { message?: string; token?: string }
    | undefined

  if (!response.ok || !data?.token) {
    throw new Error(data?.message ?? `Login failed with status ${response.status}`)
  }

  return { token: data.token }
}

export async function registerUser(
  username: string,
  email: string,
  password: string,
): Promise<void> {
  const response = await fetch(`${apiBaseUrl}/api/user`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ username, email, password }),
  })

  if (!response.ok) {
    const data = (await response.json()) as { message?: string } | undefined
    throw new Error(data?.message ?? `Registration failed with status ${response.status}`)
  }
}

export async function logoutUser(token: string): Promise<void> {
  try {
    await fetch(`${apiBaseUrl}/api/user/logout`, {
      method: 'POST',
      credentials: 'include',
      headers: { Authorization: `Bearer ${token}` },
    })
  } catch {
    // Fire-and-forget — local session is cleared regardless
  }
}
