import { DatabaseError } from "@/lib/error";
import { logError } from "@/lib/logger";
import type { RepositoryContext } from "../datastore/repository";
import { BaseRepository } from "../datastore/repository";

export const ConsoleUserSessionRepository = (ctx: RepositoryContext) => {
  const { datastore } = new BaseRepository(ctx);
  const CreateEntry = async (entry: {
    browser: string;
    console_user_id: string;
    device_type: string;
    fcm_token: string;
    ip_address: string;
    location: string;
    os: string;
    refresh_token: string;
  }) => {
    try {
      const newEntry = await datastore
        .insertInto("console_user_sessions")
        .values({
          browser: entry.browser,
          console_user_id: entry.console_user_id,
          device_type: entry.device_type,
          fcm_token: entry.fcm_token,
          ip_address: entry?.ip_address,
          location: entry.location,
          os: entry.os,
          refresh_token: entry.refresh_token,
        })
        .returningAll()
        .executeTakeFirst();
      return newEntry;
    } catch (err) {
      logError(err);
      throw new DatabaseError({
        error: err,
        message: "Failed to create new user",
      });
    }
  };

  const GetConsoleUserSession = async (sessionId: string) => {
    try {
      const sessionRecord = await datastore
        .selectFrom("console_user_sessions")
        .selectAll()
        .where("id", "=", sessionId)
        .executeTakeFirst();

      if (!sessionRecord) return null;

      const consoleUserRecord = await datastore
        .selectFrom("console_users")
        .select(["first_name", "last_name", "email", "id", "is_super_admin"])
        .where("id", "=", sessionRecord.console_user_id)
        .executeTakeFirst();

      if (!consoleUserRecord) return null;

      return {
        sessionRecord,
        consoleUserRecord,
      };
    } catch (err: any) {
      logError(err);
      return null;
    }
  };

  const UpdateEntry = async (
    id: string,
    entry: {
      browser?: string;
      device_type?: string;
      fcm_token?: string;
      ip_address?: string;
      location?: string;
      os?: string;
      refresh_token?: string;
    },
  ) => {
    try {
      const updated = await datastore
        .updateTable("console_user_sessions")
        .set(() => {
          const updates: Record<string, unknown> = {
            updated_at: new Date().toISOString().replace(/\.\d{3}Z$/, "Z"),
          };
          if (entry.browser !== undefined) {
            updates.browser = entry.browser;
          }
          if (entry.ip_address !== undefined) {
            updates.ip_address = entry.ip_address;
          }
          if (entry.device_type !== undefined) {
            updates.device_type = entry.device_type;
          }
          if (entry.fcm_token !== undefined) {
            updates.fcm_token = entry.fcm_token;
          }
          if (entry.location !== undefined) {
            updates.location = entry.location;
          }
          if (entry.os !== undefined) {
            updates.os = entry.os;
          }
          if (entry.refresh_token !== undefined) {
            updates.refresh_token = entry.refresh_token;
          }
          return updates;
        })
        .where("id", "=", id)
        .returningAll()
        .executeTakeFirstOrThrow();
      return updated;
    } catch (err) {
      logError(err);
      throw new DatabaseError({
        error: err,
        message: "Failed to find session",
      });
    }
  };

  const RemoveEntry = async (id: string) => {
    try {
      await datastore
        .deleteFrom("console_user_sessions")
        .where("id", "=", id)
        .execute();
    } catch (err) {
      logError(err);
      throw new DatabaseError({
        error: err,
        message: "Failed to find session",
      });
    }
  };

  const RemoveEntriesByUserId = async (userId: string) => {
    try {
      await datastore
        .deleteFrom("console_user_sessions")
        .where("console_user_id", "=", userId)
        .execute();
    } catch (err) {
      logError(err);
      throw new DatabaseError({
        error: err,
        message: "Failed to delete sessions for user",
      });
    }
  };

  return {
    CreateEntry,
    GetConsoleUserSession,
    UpdateEntry,
    RemoveEntry,
    RemoveEntriesByUserId,
  };
};
export type TConsoleUserSessionRepository = ReturnType<
  typeof ConsoleUserSessionRepository
>;
