import { SignJWT, jwtVerify } from "jose"
import { cookies } from "next/headers"
import { APP_CONFIG } from "./config"

const secretKey = APP_CONFIG.JWT_SECRET
const key = new TextEncoder().encode(secretKey)

export interface SessionPayload {
  userId: string
  username: string
  role: string
  expiresAt: Date
}

export async function encrypt(payload: SessionPayload) {
  return await new SignJWT(payload)
    .setProtectedHeader({ alg: "HS256" })
    .setIssuedAt()
    .setExpirationTime("24h")
    .sign(key)
}

export async function decrypt(input: string): Promise<SessionPayload> {
  const { payload } = await jwtVerify(input, key, {
    algorithms: ["HS256"],
  })
  return payload as SessionPayload
}

export async function createSession(userId: string, username: string, role: string) {
  const expiresAt = new Date(Date.now() + 24 * 60 * 60 * 1000) // 24 hours
  const session = await encrypt({ userId, username, role, expiresAt })

  cookies().set("session", session, {
    expires: expiresAt,
    httpOnly: true,
    secure: APP_CONFIG.NODE_ENV === "production",
    sameSite: "lax",
    path: "/",
  })
}

export async function verifySession() {
  const cookie = cookies().get("session")?.value
  if (!cookie) return null

  try {
    const session = await decrypt(cookie)
    if (new Date(session.expiresAt) < new Date()) {
      return null
    }
    return session
  } catch {
    return null
  }
}

export async function deleteSession() {
  cookies().delete("session")
}

// Rate limiting store (in production, use Redis)
const rateLimitStore = new Map<string, { count: number; resetTime: number }>()

export function rateLimit(identifier: string, limit = 5, windowMs: number = 15 * 60 * 1000) {
  const now = Date.now()
  const key = identifier
  const record = rateLimitStore.get(key)

  if (!record || now > record.resetTime) {
    rateLimitStore.set(key, { count: 1, resetTime: now + windowMs })
    return { success: true, remaining: limit - 1 }
  }

  if (record.count >= limit) {
    return { success: false, remaining: 0, resetTime: record.resetTime }
  }

  record.count++
  return { success: true, remaining: limit - record.count }
}
