import type { AuthInvite, AuthInviteEvent } from "@/generated/prisma/client"

import { ROLE_OPTIONS, type RoleOption, normalizeRole } from "@/lib/authz"
import { DEFAULT_TENANT_ID } from "@/lib/constants"
import { env } from "@/lib/env"

export type InviteStatus = "pending" | "accepted" | "revoked" | "expired"

export type InviteWithEvents = AuthInvite & {
  events: AuthInviteEvent[]
}

export type InviteEventPayload = {
  id: string
  type: string
  createdAt: string
  actorId: string | null
  payload: unknown
}

export type NormalizedInvite = {
  id: string
  email: string
  name: string | null
  role: RoleOption
  tenantId: string
  status: InviteStatus
  token: string
  inviteUrl: string
  expiresAt: string
  createdAt: string
  createdById: string | null
  acceptedAt: string | null
  acceptedById: string | null
  revokedAt: string | null
  revokedById: string | null
  revokedReason: string | null
  events: InviteEventPayload[]
}

const DEFAULT_APP_URL = env.NEXT_PUBLIC_APP_URL ?? env.BETTER_AUTH_URL ?? "http://localhost:3000"

export function computeInviteStatus(invite: AuthInvite, now: Date = new Date()): InviteStatus {
  if (invite.status === "revoked") return "revoked"
  if (invite.status === "accepted") return "accepted"
  if (invite.status === "expired") return "expired"
  if (invite.expiresAt.getTime() <= now.getTime()) {
    return "expired"
  }
  return "pending"
}

export function buildInviteUrl(token: string) {
  const base = DEFAULT_APP_URL.endsWith("/") ? DEFAULT_APP_URL.slice(0, -1) : DEFAULT_APP_URL
  return `${base}/invite/${token}`
}

export function normalizeRoleOption(role?: string | null): RoleOption {
  const normalized = normalizeRole(role)
  if (normalized && (ROLE_OPTIONS as readonly string[]).includes(normalized)) {
    return normalized as RoleOption
  }
  return "agent"
}

export function normalizeInvite(invite: InviteWithEvents, now: Date = new Date()): NormalizedInvite {
  const status = computeInviteStatus(invite, now)
  const inviteUrl = buildInviteUrl(invite.token)

  return {
    id: invite.id,
    email: invite.email,
    name: invite.name ?? null,
    role: normalizeRoleOption(invite.role),
    tenantId: invite.tenantId ?? DEFAULT_TENANT_ID,
    status,
    token: invite.token,
    inviteUrl,
    expiresAt: invite.expiresAt.toISOString(),
    createdAt: invite.createdAt.toISOString(),
    createdById: invite.createdById ?? null,
    acceptedAt: invite.acceptedAt ? invite.acceptedAt.toISOString() : null,
    acceptedById: invite.acceptedById ?? null,
    revokedAt: invite.revokedAt ? invite.revokedAt.toISOString() : null,
    revokedById: invite.revokedById ?? null,
    revokedReason: invite.revokedReason ?? null,
    events: invite.events
      .slice()
      .sort((a, b) => a.createdAt.getTime() - b.createdAt.getTime())
      .map((event) => ({
        id: event.id,
        type: event.type,
        createdAt: event.createdAt.toISOString(),
        actorId: event.actorId ?? null,
        payload: event.payload,
      })),
  }
}
