import { db } from '../db/db_index';
import { staffUsers, staffRoles, users, userDetails, orders } from '../db/schema';
import { eq, or, and, lt, desc, like } from 'drizzle-orm';

export interface StaffUser {
  id: number;
  name: string;
  password: string;
  staffRoleId: number;
  createdAt: Date;
}

export async function getStaffUserByName(name: string): Promise<StaffUser | null> {
  const staff = await db.query.staffUsers.findFirst({
    where: eq(staffUsers.name, name),
  });

  return staff || null;
}

export async function getAllStaff(): Promise<any[]> {
  const staff = await db.query.staffUsers.findMany({
    columns: {
      id: true,
      name: true,
    },
    with: {
      role: {
        with: {
          rolePermissions: {
            with: {
              permission: true,
            },
          },
        },
      },
    },
  });

  return staff;
}

export async function getStaffByName(name: string): Promise<StaffUser | null> {
  const staff = await db.query.staffUsers.findFirst({
    where: eq(staffUsers.name, name),
  });
  return staff || null;
}

export async function getAllUsers(
  cursor?: number,
  limit: number = 20,
  search?: string
): Promise<{ users: any[]; hasMore: boolean }> {
  let whereCondition = undefined;

  if (search) {
    whereCondition = or(
      like(users.name, `%${search}%`),
      like(users.email, `%${search}%`),
      like(users.mobile, `%${search}%`)
    );
  }

  if (cursor) {
    const cursorCondition = lt(users.id, cursor);
    whereCondition = whereCondition ? and(whereCondition, cursorCondition) : cursorCondition;
  }

  const allUsers = await db.query.users.findMany({
    where: whereCondition,
    with: {
      userDetails: true,
    },
    orderBy: desc(users.id),
    limit: limit + 1,
  });

  const hasMore = allUsers.length > limit;
  const usersToReturn = hasMore ? allUsers.slice(0, limit) : allUsers;

  return { users: usersToReturn, hasMore };
}

export async function getUserWithDetails(userId: number): Promise<any | null> {
  const user = await db.query.users.findFirst({
    where: eq(users.id, userId),
    with: {
      userDetails: true,
      orders: {
        orderBy: desc(orders.createdAt),
        limit: 1,
      },
    },
  });

  return user || null;
}

export async function updateUserSuspension(userId: number, isSuspended: boolean): Promise<void> {
  await db
    .insert(userDetails)
    .values({ userId, isSuspended })
    .onConflictDoUpdate({
      target: userDetails.userId,
      set: { isSuspended },
    });
}

export async function checkStaffUserExists(name: string): Promise<boolean> {
  const existingUser = await db.query.staffUsers.findFirst({
    where: eq(staffUsers.name, name),
  });
  return !!existingUser;
}

export async function checkStaffRoleExists(roleId: number): Promise<boolean> {
  const role = await db.query.staffRoles.findFirst({
    where: eq(staffRoles.id, roleId),
  });
  return !!role;
}

export async function createStaffUser(
  name: string,
  password: string,
  roleId: number
): Promise<StaffUser> {
  const [newUser] = await db.insert(staffUsers).values({
    name: name.trim(),
    password,
    staffRoleId: roleId,
  }).returning();

  return {
    id: newUser.id,
    name: newUser.name,
    password: newUser.password,
    staffRoleId: newUser.staffRoleId ?? roleId,
    createdAt: newUser.createdAt,
  };
}

export async function getAllRoles(): Promise<any[]> {
  const roles = await db.query.staffRoles.findMany({
    columns: {
      id: true,
      roleName: true,
    },
  });

  return roles;
}
