import prisma from "../config/prisma.js";
import { Prisma } from "../generated/prisma/client.js";

export class EmployeeRepository {
  async create(data: Prisma.EmployeeUncheckedCreateInput) {
    return prisma.employee.create({ data });
  }

  async findAll(skip?: number, take?: number, search?: string, status?: boolean) {
    const where: Prisma.EmployeeWhereInput = {
      deletedAt: null,
    };

    if (status !== undefined) {
      where.status = status;
    }

    if (search && search.trim() !== "") {
      const searchTrim = search.trim();
      where.OR = [
        { name: { contains: searchTrim } },
        { employeeCode: { contains: searchTrim } },
        { mobile: { contains: searchTrim } },
        { designation: { contains: searchTrim } },
      ];
    }

    const [items, total] = await Promise.all([
      prisma.employee.findMany({
        where,
        ...(skip !== undefined ? { skip } : {}),
        ...(take !== undefined ? { take } : {}),
        orderBy: { id: 'desc' },
      }),
      prisma.employee.count({ where }),
    ]);

    return { items, total };
  }

  async findById(id: bigint) {
    return prisma.employee.findFirst({
      where: { id, deletedAt: null },
    });
  }

  async findByCode(employeeCode: string) {
    return prisma.employee.findFirst({
      where: { employeeCode, deletedAt: null },
    });
  }

  async findByNameAndMobile(name: string, mobile?: string | null, excludeId?: bigint) {
    const cleanMobile = mobile?.trim();
    return prisma.employee.findFirst({
      where: {
        name: {
          equals: name.trim(),
        },
        ...(cleanMobile ? { mobile: { equals: cleanMobile } } : { mobile: null }),
        deletedAt: null,
        ...(excludeId ? { id: { not: excludeId } } : {}),
      },
    });
  }


  async update(id: bigint, data: Prisma.EmployeeUpdateInput) {
    return prisma.employee.update({
      where: { id },
      data,
    });
  }

  async delete(id: bigint) {
    // Soft delete
    return prisma.employee.update({
      where: { id },
      data: { deletedAt: new Date(), status: false },
    });
  }

  async generateEmployeeCode(): Promise<string> {
    const lastEmp = await prisma.employee.findFirst({
      orderBy: { id: "desc" },
      select: { id: true, employeeCode: true },
    });

    let nextNum = 1;
    if (lastEmp) {
      const match = lastEmp.employeeCode.match(/\d+/);
      if (match) {
        nextNum = parseInt(match[0], 10) + 1;
      } else {
        nextNum = Number(lastEmp.id) + 1;
      }
    }

    // Ensure generated code is unique
    let candidate = `EMP${String(nextNum).padStart(3, "0")}`;
    let existing = await this.findByCode(candidate);
    while (existing) {
      nextNum++;
      candidate = `EMP${String(nextNum).padStart(3, "0")}`;
      existing = await this.findByCode(candidate);
    }

    return candidate;
  }
}


