import { cookies, headers } from "next/headers"
import { redirect } from "next/navigation"

import { env } from "@/lib/env"
import { isAdmin, isStaff } from "@/lib/authz"
import { auth } from "@/lib/auth"

type ServerSession = {
  session: {
    id: string
    expiresAt: number
  }
  user: {
    id: string
    name: string
    email: string
    role: string
    tenantId: string | null
    avatarUrl: string | null
    machinePersona: string | null
  }
}

async function serializeCookies() {
  const store = await cookies()
  return store.getAll().map((cookie) => `${cookie.name}=${cookie.value}`).join("; ")
}

async function buildRequest() {
  const cookieHeader = await serializeCookies()
  const headerList = await headers()
  const userAgent = headerList.get("user-agent") ?? ""
  const ip =
    headerList.get("x-forwarded-for") ||
    headerList.get("x-real-ip") ||
    headerList.get("cf-connecting-ip") ||
    headerList.get("x-client-ip") ||
    undefined

  // Evitar fallback para localhost em produção: tenta BETTER_AUTH_URL,
  // depois NEXT_PUBLIC_APP_URL e, por fim, o host do próprio request.
  const forwardedProto = headerList.get("x-forwarded-proto")
  const forwardedHost = headerList.get("x-forwarded-host") ?? headerList.get("host")
  const requestOrigin = forwardedProto && forwardedHost ? `${forwardedProto}://${forwardedHost}` : undefined
  const baseUrl = env.BETTER_AUTH_URL || env.NEXT_PUBLIC_APP_URL || requestOrigin || "http://localhost:3000"

  return new Request(baseUrl, {
    headers: {
      cookie: cookieHeader,
      "user-agent": userAgent,
      ...(ip ? { "x-forwarded-for": ip } : {}),
    },
  })
}

export async function getServerSession(): Promise<ServerSession | null> {
  try {
    // Dev-only bypass to simplify local dashboard access when auth is misconfigured.
    if (process.env.NODE_ENV !== "production" && process.env.DEV_BYPASS_AUTH === "1") {
      return {
        session: {
          id: "dev-session",
          expiresAt: Date.now() + 1000 * 60 * 60,
        },
        user: {
          id: "dev-user",
          name: "Dev Admin",
          email: "admin@sistema.dev",
          role: "admin",
          tenantId: "tenant-atlas",
          avatarUrl: null,
          machinePersona: null,
        },
      }
    }
    const request = await buildRequest()
    const session = await auth.api.getSession({
      headers: request.headers,
      request,
    })
    if (!session) return null

    const expiresValue = session.session.expiresAt
    const expiresAt =
      expiresValue instanceof Date
        ? expiresValue.getTime()
        : typeof expiresValue === "number"
          ? expiresValue
          : expiresValue
            ? new Date(expiresValue).getTime()
            : Date.now()

    return {
      session: {
        id: session.session.id,
        expiresAt,
      },
      user: {
        id: session.user.id,
        name: session.user.name,
        email: session.user.email,
        role: (session.user as { role?: string }).role ?? "agent",
        tenantId: (session.user as { tenantId?: string | null }).tenantId ?? null,
        avatarUrl: (session.user as { avatarUrl?: string | null }).avatarUrl ?? null,
        machinePersona: (session.user as { machinePersona?: string | null }).machinePersona ?? null,
      },
    }
  } catch (error) {
    console.error("Failed to read Better Auth session", error)
    return null
  }
}

export async function assertAuthenticatedSession() {
  const session = await getServerSession()
  return session?.user ? session : null
}

export async function requireAuthenticatedSession() {
  const session = await assertAuthenticatedSession()
  if (!session) {
    redirect("/login")
  }
  return session
}

export async function assertStaffSession() {
  const session = await assertAuthenticatedSession()
  if (!session) return null
  if (!isStaff(session.user.role)) {
    return null
  }
  return session
}

export async function requireStaffSession() {
  const session = await assertStaffSession()
  if (!session) {
    redirect("/portal")
  }
  return session
}

export async function assertAdminSession() {
  const session = await assertAuthenticatedSession()
  if (!session) return null
  if (!isAdmin(session.user.role)) {
    return null
  }
  return session
}

export async function requireAdminSession() {
  const session = await assertAdminSession()
  if (!session) {
    redirect("/dashboard")
  }
  return session
}
