import { createHash, randomBytes } from 'crypto';
import type { RowDataPacket } from 'mysql2';
import { cookies } from 'next/headers';

import { getPool } from '@/lib/db';

export const SESSION_COOKIE = 'admin_session';
const SESSION_MAX_AGE_SEC = 60 * 60 * 24 * 7; // 7 days

export type AdminUserRow = {
  id: number;
  email: string;
  password_hash: string;
  is_approved: boolean;
  is_admin: boolean;
};

function hashToken(token: string): string {
  return createHash('sha256').update(token, 'utf8').digest('hex');
}

export async function createSession(userId: number): Promise<string> {
  const token = randomBytes(32).toString('hex');
  const tokenHash = hashToken(token);
  const expiresAt = new Date(Date.now() + SESSION_MAX_AGE_SEC * 1000);

  const pool = getPool();
  await pool.query(
    `INSERT INTO admin_sessions (user_id, token_hash, expires_at) VALUES (?, ?, ?)`,
    [userId, tokenHash, expiresAt]
  );

  const cookieStore = await cookies();
  cookieStore.set(SESSION_COOKIE, token, {
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    sameSite: 'lax',
    maxAge: SESSION_MAX_AGE_SEC,
    path: '/',
  });

  return token;
}

export async function destroySession(): Promise<void> {
  const cookieStore = await cookies();
  const token = cookieStore.get(SESSION_COOKIE)?.value;
  if (token) {
    const pool = getPool();
    await pool.query(
      'DELETE FROM admin_sessions WHERE token_hash = ?',
      [hashToken(token)]
    );
  }
  cookieStore.delete(SESSION_COOKIE);
}

export async function getSessionUser(): Promise<AdminUserRow | null> {
  const cookieStore = await cookies();
  const token = cookieStore.get(SESSION_COOKIE)?.value;
  if (!token) {
    return null;
  }

  const tokenHash = hashToken(token);
  const pool = getPool();
  const [rows] = await pool.query<RowDataPacket[]>(
    `SELECT u.id, u.email, u.password_hash, u.is_approved, u.is_admin
     FROM admin_sessions s
     JOIN admin_users u ON u.id = s.user_id
     WHERE s.token_hash = ? AND s.expires_at > NOW()`,
    [tokenHash]
  );

  if (rows.length === 0) {
    cookieStore.delete(SESSION_COOKIE);
    return null;
  }

  const row = rows[0] as Record<string, unknown>;
  return {
    id: row.id as number,
    email: row.email as string,
    password_hash: row.password_hash as string,
    is_approved: Boolean(row.is_approved),
    is_admin: Boolean(row.is_admin),
  };
}
