import { SignJWT, jwtVerify } from 'jose';
import { NextRequest } from 'next/server';

const ALGORITHM = 'HS256';
const TOKEN_EXP_HOURS = 24;

function getSecret() {
  const secret = process.env.AUTH_SECRET || 'dev-auth-secret';
  return new TextEncoder().encode(secret);
}

export async function signAccessToken(payload: { userId: string; role: string }) {
  const secret = getSecret();
  const exp = Math.floor(Date.now() / 1000) + TOKEN_EXP_HOURS * 3600;
  return new SignJWT(payload).setProtectedHeader({ alg: ALGORITHM }).setExpirationTime(exp).sign(secret);
}

export async function verifyAccessToken(token: string) {
  const secret = getSecret();
  const { payload } = await jwtVerify(token, secret, { algorithms: [ALGORITHM] });
  return payload as { userId: string; role: string };
}

export async function getAuthFromRequest(request: Request | NextRequest) {
  let token: string | null = null;

  const header = request.headers.get('authorization');
  if (header?.startsWith('Bearer ')) {
    token = header.slice('Bearer '.length);
  }

  if (!token) {
    const cookieHeader = request.headers.get('cookie') ?? '';
    const match = cookieHeader.split(';').map((c) => c.trim()).find((c) => c.startsWith('session_token='));
    if (match) {
      token = decodeURIComponent(match.split('=')[1]);
    }
  }

  if (!token) {
    return null;
  }
  try {
    return await verifyAccessToken(token);
  } catch {
    return null;
  }
}

export async function requireAuth(request: Request | NextRequest) {
  const auth = await getAuthFromRequest(request);
  if (!auth) {
    throw new Error('Unauthorized');
  }
  return auth;
}

export function buildSessionCookie(token: string) {
  const secure = process.env.APP_URL?.startsWith('https://') || process.env.NODE_ENV === 'production';
  const maxAge = TOKEN_EXP_HOURS * 3600;
  return `session_token=${encodeURIComponent(token)}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${maxAge};${secure ? ' Secure;' : ''}`;
}

export function clearSessionCookie() {
  return 'session_token=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0;';
}
