import { encrypt } from "@/lib/cipher";
import { createConsoleUserSession, verifySession } from "@/lib/session";
import type { TConsoleUserSessionRepository } from "./console-user-session.repository";

interface TConsoleUserSessionServiceDeps {
  ConsoleUserSessionRepository: TConsoleUserSessionRepository;
}

export const ConsoleUserSessionServices = ({
  ConsoleUserSessionRepository,
}: TConsoleUserSessionServiceDeps) => {
  const CreateSession = async (sessionData: {
    browser: string;
    console_user_id: string;
    device_type: string;
    fcm_token: string;
    ip_address: string;
    location: string;
    os: string;
    refresh_token: string;
  }) => {
    try {
      const newRecord =
        await ConsoleUserSessionRepository.CreateEntry(sessionData);
      return newRecord;
    } catch (err) {
      throw err;
    }
  };

  const GetUserSession = async (sessionId: string) => {
    try {
      const sessionRecord =
        await ConsoleUserSessionRepository.GetConsoleUserSession(sessionId);
      return sessionRecord;
    } catch (err) {
      throw err;
    }
  };

  const RotateSession = async (entry: {
    fcm_token?: string;
    ip_address?: string;
    location?: string;
    browser?: string;
    device_type?: string;
    os?: string;
    kcSessionId: string;
  }) => {
    try {
      // fetch session using sessionId
      const session = await ConsoleUserSessionRepository.GetConsoleUserSession(
        entry.kcSessionId,
      );
      if (!session || !session.sessionRecord || !session.consoleUserRecord) {
        return null;
      }
      const { consoleUserRecord, sessionRecord } = session;
      // verify refreshtoken in session
      const isValid = await verifySession(sessionRecord?.refresh_token);
      if (!isValid) {
        return null;
      }
      // if verified then create new sessionToken and update the session in sessions table
      const { dbSessionToken, sessionToken } = await createConsoleUserSession(
        consoleUserRecord.email,
      );
      const encryptedSessionToken = encrypt(sessionToken);
      const newSession = await ConsoleUserSessionRepository.UpdateEntry(
        sessionRecord.id,
        {
          browser: entry.browser,
          device_type: entry.device_type,
          fcm_token: entry.fcm_token,
          ip_address: entry.ip_address,
          location: entry.location,
          os: entry.os,
          refresh_token: dbSessionToken,
        },
      );
      return {
        ...newSession,
        encryptedSessionToken,
      };
    } catch (err) {
      throw err;
    }
  };

  const DeleteSession = async (id: string) => {
    try {
      await ConsoleUserSessionRepository.RemoveEntry(id);
    } catch (err) {
      throw err;
    }
  };

  const DeleteSessionByUserId = async (userId: string) => {
    try {
      await ConsoleUserSessionRepository.RemoveEntriesByUserId(userId);
    } catch (err) {
      throw err;
    }
  };

  return {
    CreateSession,
    GetUserSession,
    RotateSession,
    DeleteSession,
    DeleteSessionByUserId,
  };
};

export type TConsoleUserSessionServices = ReturnType<
  typeof ConsoleUserSessionServices
>;
