import bcrypt from "bcryptjs";
import { cookies } from "next/headers";
import { createHash, randomBytes } from "node:crypto";
import { prisma } from "./db";

const COOKIE = "am_session";
const SESSION_KEY = "auth.sessionToken";
const PASSWORD_KEY = "auth.passwordHash";

function sha256(s: string): string {
  return createHash("sha256").update(s).digest("hex");
}

export async function getPasswordHash(): Promise<string | null> {
  const r = await prisma.setting.findUnique({ where: { key: PASSWORD_KEY } });
  return r?.value ?? null;
}

export async function setPassword(plain: string): Promise<void> {
  const hash = await bcrypt.hash(plain, 10);
  await prisma.setting.upsert({
    where: { key: PASSWORD_KEY },
    create: { key: PASSWORD_KEY, value: hash },
    update: { value: hash },
  });
}

export async function verifyPassword(plain: string): Promise<boolean> {
  const hash = await getPasswordHash();
  if (!hash) return false;
  return bcrypt.compare(plain, hash);
}

async function getSessionToken(): Promise<string | null> {
  const r = await prisma.setting.findUnique({ where: { key: SESSION_KEY } });
  return r?.value ?? null;
}

export async function login(plain: string): Promise<boolean> {
  if (!(await verifyPassword(plain))) return false;
  const token = randomBytes(32).toString("hex");
  await prisma.setting.upsert({
    where: { key: SESSION_KEY },
    create: { key: SESSION_KEY, value: sha256(token) },
    update: { value: sha256(token) },
  });
  const c = await cookies();
  c.set(COOKIE, token, {
    httpOnly: true,
    sameSite: "lax",
    secure: false,
    path: "/",
    maxAge: 60 * 60 * 24 * 30,
  });
  return true;
}

export async function logout(): Promise<void> {
  const c = await cookies();
  c.delete(COOKIE);
  await prisma.setting.deleteMany({ where: { key: SESSION_KEY } });
}

export async function isAuthed(): Promise<boolean> {
  const c = await cookies();
  const token = c.get(COOKIE)?.value;
  if (!token) return false;
  const stored = await getSessionToken();
  if (!stored) return false;
  return sha256(token) === stored;
}
