import { SignJWT, jwtVerify } from "jose";
import bcrypt from "bcryptjs";
import { randomBytes, createHash } from "crypto";
import { cookies } from "next/headers";
import type { Role } from "./enums";

const secret = new TextEncoder().encode(
  process.env.JWT_SECRET || "dev-secret-change-me"
);
const ACCESS_TTL_MIN = Number(process.env.ACCESS_TOKEN_TTL_MIN || 15);
// "Login tersimpan" — sesi diingat per-perangkat, reset (wajib klik lagi) tiap
// sekian hari. Jendela ini sliding: setiap kali dipakai (klik "Lanjutkan" atau
// pemakaian aplikasi normal), diperpanjang lagi dari 0.
const REMEMBER_TTL_DAYS = Number(process.env.REFRESH_TOKEN_TTL_DAYS || 1);

export const ACCESS_COOKIE = "access_token";
export const REMEMBER_COOKIE = "remember_token";
// Cookie non-httpOnly, hanya untuk data tampilan ("Lanjutkan sebagai ...") —
// TIDAK dipakai untuk autentikasi (autentikasi asli lewat REMEMBER_COOKIE).
export const REMEMBERED_DISPLAY_COOKIE = "remembered_user";

export interface SessionUser {
  id: string;
  role: Role;
  branchId: string | null;
  name: string;
  email: string;
}

export async function hashPassword(pw: string): Promise<string> {
  return bcrypt.hash(pw, 10);
}
export async function verifyPassword(pw: string, hash: string): Promise<boolean> {
  return bcrypt.compare(pw, hash);
}

export async function signAccessToken(u: SessionUser): Promise<string> {
  return new SignJWT({
    role: u.role,
    branchId: u.branchId,
    name: u.name,
    email: u.email,
  })
    .setProtectedHeader({ alg: "HS256" })
    .setSubject(u.id)
    .setIssuedAt()
    .setExpirationTime(`${ACCESS_TTL_MIN}m`)
    .sign(secret);
}

export async function verifyAccessToken(token: string): Promise<SessionUser | null> {
  try {
    const { payload } = await jwtVerify(token, secret);
    return {
      id: String(payload.sub),
      role: payload.role as Role,
      branchId: (payload.branchId as string | null) ?? null,
      name: payload.name as string,
      email: payload.email as string,
    };
  } catch {
    return null;
  }
}

// Set / clear cookie (httpOnly). Dipanggil di route handler login/logout.
export function setAuthCookie(token: string) {
  cookies().set(ACCESS_COOKIE, token, {
    httpOnly: true,
    sameSite: "lax",
    secure: process.env.NODE_ENV === "production",
    path: "/",
    maxAge: ACCESS_TTL_MIN * 60,
  });
}
export function clearAuthCookie() {
  cookies().set(ACCESS_COOKIE, "", { httpOnly: true, path: "/", maxAge: 0 });
}

// Ambil sesi user dari cookie (untuk route handler / server component).
export async function getSession(): Promise<SessionUser | null> {
  const token = cookies().get(ACCESS_COOKIE)?.value;
  if (!token) return null;
  return verifyAccessToken(token);
}

// --- "Login tersimpan" (remember-this-device) -----------------------------
// Token acak (bukan JWT) yang di-hash (SHA-256) sebelum disimpan di tabel
// RefreshToken — hanya hash yang tersimpan di DB, token asli hanya ada di
// cookie httpOnly milik browser/perangkat.

export interface RememberDisplay {
  name: string;
  role: Role;
  branchName: string | null;
}

export function generateRememberToken(): { raw: string; hash: string; expiresAt: Date } {
  const raw = randomBytes(32).toString("hex");
  const hash = hashRememberToken(raw);
  const expiresAt = new Date(Date.now() + REMEMBER_TTL_DAYS * 24 * 60 * 60 * 1000);
  return { raw, hash, expiresAt };
}

export function hashRememberToken(raw: string): string {
  return createHash("sha256").update(raw).digest("hex");
}

// Set cookie token (httpOnly, dipakai autentikasi) + cookie tampilan (dibaca
// client-side untuk kartu "Lanjutkan sebagai ...", TIDAK dipakai untuk auth).
export function setRememberCookies(raw: string, expiresAt: Date, display: RememberDisplay) {
  const secure = process.env.NODE_ENV === "production";
  cookies().set(REMEMBER_COOKIE, raw, {
    httpOnly: true, sameSite: "lax", secure, path: "/", expires: expiresAt,
  });
  cookies().set(REMEMBERED_DISPLAY_COOKIE, JSON.stringify(display), {
    httpOnly: false, sameSite: "lax", secure, path: "/", expires: expiresAt,
  });
}

export function clearRememberCookies() {
  cookies().set(REMEMBER_COOKIE, "", { httpOnly: true, path: "/", maxAge: 0 });
  cookies().set(REMEMBERED_DISPLAY_COOKIE, "", { httpOnly: false, path: "/", maxAge: 0 });
}
