import {
  cookies,
  headers,
  type UnsafeUnwrappedCookies,
  type UnsafeUnwrappedHeaders,
} from "next/headers";
import { prisma } from "@/lib/prisma";
import { hashIp, randomToken, sha256 } from "@/lib/security";

export const SESSION_COOKIE = "toolaro_session";

export function getClientIp() {
  const h = headers() as unknown as UnsafeUnwrappedHeaders;
  return (
    h.get("x-forwarded-for")?.split(",")[0]?.trim() ??
    h.get("x-real-ip") ??
    "127.0.0.1"
  );
}

export function getUserAgent() {
  return (headers() as unknown as UnsafeUnwrappedHeaders).get("user-agent") ?? "";
}

export function shouldUseSecureCookies() {
  if (process.env.NODE_ENV !== "production") return false;
  const h = headers() as unknown as UnsafeUnwrappedHeaders;
  const host = h.get("host") ?? "";
  return !host.startsWith("localhost:") && !host.startsWith("127.0.0.1:") && !host.includes("[::1]");
}

export async function createSession(userId: string) {
  const token = randomToken(48);
  const expiresAt = new Date(Date.now() + 1000 * 60 * 60 * 24 * 30);
  await prisma.userSession.create({
    data: {
      userId,
      sessionToken: sha256(token),
      expiresAt,
      ipHash: hashIp(getClientIp()),
      userAgent: getUserAgent().slice(0, 500),
    },
  });

  (cookies() as unknown as UnsafeUnwrappedCookies).set(SESSION_COOKIE, token, {
    httpOnly: true,
    sameSite: "lax",
    secure: shouldUseSecureCookies(),
    path: "/",
    expires: expiresAt,
  });
}

export async function clearSession() {
  const token = (cookies() as unknown as UnsafeUnwrappedCookies).get(SESSION_COOKIE)?.value;
  if (token) {
    await prisma.userSession.deleteMany({ where: { sessionToken: sha256(token) } });
  }
  (cookies() as unknown as UnsafeUnwrappedCookies).delete(SESSION_COOKIE);
}

export async function getCurrentUser() {
  const token = (cookies() as unknown as UnsafeUnwrappedCookies).get(SESSION_COOKIE)?.value;
  if (!token) return null;

  const session = await prisma.userSession.findUnique({
    where: { sessionToken: sha256(token) },
    include: {
      user: {
        include: {
          subscriptions: { orderBy: { createdAt: "desc" }, take: 1 },
          favorites: true,
          toolSettings: true,
        },
      },
    },
  });

  if (!session || session.expiresAt <= new Date()) return null;
  await prisma.userSession.update({
    where: { id: session.id },
    data: { lastSeenAt: new Date() },
  });
  return session.user;
}

export function hasPremium(user: Awaited<ReturnType<typeof getCurrentUser>>) {
  if (!user) return false;
  if (user.premiumUntil && user.premiumUntil > new Date()) return true;
  return ["active", "trialing"].includes(user.premiumStatus);
}

export async function requireUser() {
  const user = await getCurrentUser();
  if (!user) throw new Error("UNAUTHORIZED");
  return user;
}
