import { eq } from "drizzle-orm";
import { SignJWT } from "jose";
import db from "../../db";
import { authSessions } from "../../db/schema/authSessions";
import type { SessionMetadata } from "./types";

// JWT секрет (лучше вынести в .env)
const JWT_SECRET = new TextEncoder().encode(
  process.env.JWT_SECRET || "your-secret-key-change-this"
);

const TOKEN_EXPIRATION_DAYS = 7;

/**
 * Сервис для работы с сессиями
 */
export const sessionService = {
  /**
   * Создать новую сессию
   */
  async create(
    userId: string,
    metadata: SessionMetadata
  ): Promise<{ sessionId: string; accessToken: string }> {
    const sessionId = crypto.randomUUID();

    // Создать JWT токен с id сессии
    const accessToken = await new SignJWT({ id: sessionId })
      .setProtectedHeader({ alg: "HS256" })
      .setIssuedAt()
      .setExpirationTime(`${TOKEN_EXPIRATION_DAYS}d`)
      .sign(JWT_SECRET);

    // Захешировать токен через bcrypt для хранения в БД
    const accessTokenHash = await Bun.password.hash(accessToken, {
      algorithm: "bcrypt",
    });

    // Вычислить дату истечения
    const expiresAt = new Date();
    expiresAt.setDate(expiresAt.getDate() + TOKEN_EXPIRATION_DAYS);

    // Сохранить сессию в БД
    await db.insert(authSessions).values({
      id: sessionId,
      userId,
      accessTokenHash,
      userAgent: metadata.userAgent,
      ipAddress: metadata.ipAddress,
      expiresAt,
    });

    return { sessionId, accessToken };
  },

  /**
   * Отозвать сессию (logout)
   */
  async revoke(sessionId: string): Promise<void> {
    await db
      .update(authSessions)
      .set({ revokedAt: new Date() })
      .where(eq(authSessions.id, sessionId));
  },

  /**
   * Получить сессию по ID
   */
  async findById(sessionId: string) {
    const session = (
      await db
        .select()
        .from(authSessions)
        .where(eq(authSessions.id, sessionId))
        .limit(1)
    )[0];

    return session || null;
  },
};
