import { prisma } from '@/lib/prisma';
import type { OpenShiftInput, CloseShiftInput } from '@/schemas/shift.schema';

export async function getCurrentShift(userId: string) {
  return prisma.cashShift.findFirst({
    where: { userId, status: 'OPEN' },
    include: {
      user: { select: { id: true, name: true } },
      _count: { select: { payments: true } },
    },
  });
}

export async function getAnyOpenShift() {
  return prisma.cashShift.findFirst({
    where: { status: 'OPEN' },
    include: { user: { select: { id: true, name: true } } },
    orderBy: { openedAt: 'desc' },
  });
}

export async function openShift(data: OpenShiftInput, userId: string) {
  // Verificar que el usuario no tenga un turno ya abierto
  const existing = await prisma.cashShift.findFirst({
    where: { userId, status: 'OPEN' },
  });
  if (existing) throw new Error('SHIFT_ALREADY_OPEN');

  return prisma.cashShift.create({
    data: { userId, initialAmount: data.initialAmount, status: 'OPEN' },
    include: { user: { select: { id: true, name: true } } },
  });
}

export async function closeShift(
  shiftId: string,
  data: CloseShiftInput,
  callerId: string,
  callerRole: string
) {
  return prisma.$transaction(async (tx) => {
    const shift = await tx.cashShift.findUnique({
      where: { id: shiftId },
      include: {
        payments: { select: { amount: true, method: true } },
      },
    });

    if (!shift) throw new Error('SHIFT_NOT_OPEN');
    if (shift.status !== 'OPEN') throw new Error('SHIFT_NOT_OPEN');

    const isOwner = shift.userId === callerId;
    const isManager = callerRole === 'ADMIN' || callerRole === 'MANAGER';
    if (!isOwner && !isManager) throw new Error('FORBIDDEN_SHIFT_OWNER');

    // Calcular monto esperado del sistema
    const systemAmount =
      Number(shift.initialAmount) +
      shift.payments
        .filter((p) => p.method === 'CASH')
        .reduce((acc, p) => acc + Number(p.amount), 0);

    const difference = data.declaredAmount - systemAmount;

    return tx.cashShift.update({
      where: { id: shiftId },
      data: {
        status: 'CLOSED',
        declaredAmount: data.declaredAmount,
        systemAmount,
        difference,
        closedAt: new Date(),
      },
      include: { user: { select: { name: true } } },
    });
  });
}

export async function getShiftHistory(page = 1, limit = 20) {
  const skip = (page - 1) * limit;
  const [shifts, total] = await prisma.$transaction([
    prisma.cashShift.findMany({
      skip,
      take: limit,
      include: {
        user: { select: { id: true, name: true } },
        _count: { select: { payments: true } },
      },
      orderBy: { openedAt: 'desc' },
    }),
    prisma.cashShift.count(),
  ]);
  return { shifts, total, page, limit };
}
