import { prisma } from "../../config/prisma";
import { Role, EmployeeStatus } from "@prisma/client";

// ---------- INVITE STAGE ----------

export function createInvitation(data: {
  organizationId: string;
  email: string;
  name: string;
  phone?: string;
  gender?: string;
  role: Role;
  departmentId?: string;
  token: string;
  expiresAt: Date;
}) {
  return prisma.employee.create({
    data: {
      organizationId: data.organizationId,
      email: data.email,
      name: data.name,
      phone: data.phone ?? null,
      gender: data.gender ?? null,
      role: data.role,
      departmentId: data.departmentId ?? null,
      token: data.token,
      expiresAt: data.expiresAt,
      status: "INVITED",
    },
  });
}

export function findInvitationByToken(token: string) {
  return prisma.employee.findUnique({ where: { token } });
}

export function findInvitationByEmail(organizationId: string, email: string) {
  return prisma.employee.findFirst({
    where: { organizationId, email, status: "INVITED" },
  });
}

// ---------- ACCEPT STAGE ----------

export function acceptInvitation(data: {
  employeeId: string;
  organizationId: string;
  name: string;
  email: string;
  passwordHash: string;
  role: Role;
}) {
  return prisma.$transaction(async (tx) => {
    const user = await tx.user.create({
      data: {
        organizationId: data.organizationId,
        name: data.name,
        email: data.email,
        passwordHash: data.passwordHash,
        role: data.role,
        status: "ACTIVE",
      },
    });

    const employee = await tx.employee.update({
      where: { id: data.employeeId },
      data: {
        userId: user.id,
        status: "ACTIVE",
        token: null,
        expiresAt: null,
      },
    });

    return { user, employee };
  });
}

// ---------- QUERIES ----------

export async function findEmployeesByOrg(
  organizationId: string,
  page: number,
  limit: number,
  search?: string,
  status?: EmployeeStatus,
  role?: Role,
) {
  const where = {
    organizationId,
    ...(status ? { status } : {}),
    ...(role ? { role } : {}),
    ...(search
      ? {
          OR: [
            { name: { contains: search } },
            { email: { contains: search } },
          ],
        }
      : {}),
  };
  const [data, total] = await Promise.all([
    prisma.employee.findMany({
      where,
      include: {
        user: { select: { id: true, name: true, email: true, role: true, status: true } },
        department: { select: { id: true, name: true } },
      },
      orderBy: { createdAt: "desc" },
      skip: (page - 1) * limit,
      take: limit,
    }),
    prisma.employee.count({ where }),
  ]);
  return { data, total };
}

export function findEmployeeById(id: string, organizationId: string) {
  return prisma.employee.findFirst({
    where: { id, organizationId },
    include: {
      user: { select: { id: true, name: true, email: true, role: true, status: true, phone: true } },
      department: { select: { id: true, name: true } },
      organization: { select: { id: true, name: true } },
    },
  });
}

export function updateEmployee(
  id: string,
  data: { name?: string; role?: Role; departmentId?: string; phone?: string; gender?: string; status?: string }
) {
  return prisma.$transaction(async (tx) => {
    const emp = await tx.employee.update({
      where: { id },
      data: {
        ...(data.name ? { name: data.name } : {}),
        ...(data.role ? { role: data.role } : {}),
        ...(data.departmentId !== undefined ? { departmentId: data.departmentId || null } : {}),
        ...(data.phone !== undefined ? { phone: data.phone || null } : {}),
        ...(data.gender !== undefined ? { gender: data.gender || null } : {}),
        ...(data.status ? { status: data.status as EmployeeStatus } : {}),
      },
      include: { department: { select: { id: true, name: true } } },
    });

    // Sync matching fields to User table
    if (emp.userId) {
      const userUpdate: any = {};
      if (data.name) userUpdate.name = data.name;
      if (data.role) userUpdate.role = data.role;
      if (data.status) {
        const statusMap: Record<string, string> = {
          ACTIVE: "ACTIVE",
          SUSPENDED: "SUSPENDED",
          REVOKED: "INACTIVE",
          INVITED: "ACTIVE",
        };
        userUpdate.status = statusMap[data.status] ?? "ACTIVE";
      }
      if (Object.keys(userUpdate).length > 0) {
        await tx.user.update({ where: { id: emp.userId }, data: userUpdate });
      }
    }

    return emp;
  });
}

export function deleteEmployee(id: string) {
  return prisma.$transaction(async (tx) => {
    const emp = await tx.employee.findUnique({ where: { id }, select: { userId: true } });
    await tx.employee.delete({ where: { id } });
    if (emp?.userId) await tx.user.delete({ where: { id: emp.userId } });
  });
}
