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

export class CustomerReceiptRepository {
  async create(data: Prisma.CustomerReceiptUncheckedCreateInput) {
    return prisma.customerReceipt.create({
      data,
      include: {
        customer: { select: { name: true, outstandingBalance: true } },
      },
    });
  }

  async findAll(
    skip?: number,
    take?: number,
    customerId?: bigint,
    dateFrom?: Date,
    dateTo?: Date,
    search?: string
  ) {
    const where: Prisma.CustomerReceiptWhereInput = { deletedAt: null };

    if (customerId) where.customerId = customerId;

    if (dateFrom || dateTo) {
      where.receiptDate = {};
      if (dateFrom) where.receiptDate.gte = dateFrom;
      if (dateTo) where.receiptDate.lte = dateTo;
    }

    const trimmedSearch = search?.trim();
    if (trimmedSearch) {
      const orFilters: Prisma.CustomerReceiptWhereInput[] = [
        { customer: { name: { contains: trimmedSearch } } },
        { referenceNo: { contains: trimmedSearch } },
        { remarks: { contains: trimmedSearch } },
      ];

      const normalizedMode = trimmedSearch.toUpperCase();
      if (["CASH", "BANK", "UPI"].includes(normalizedMode)) {
        orFilters.push({ paymentMode: normalizedMode as any });
      }

      where.OR = orFilters;
    }

    const findOptions: any = {
      where,
      include: {
        customer: { select: { name: true } },
        createdByUser: { select: { name: true } },
      },
      orderBy: { id: 'desc' },
    };

    if (skip !== undefined) findOptions.skip = skip;
    if (take !== undefined) findOptions.take = take;

    const [items, total] = await Promise.all([
      prisma.customerReceipt.findMany(findOptions),
      prisma.customerReceipt.count({ where }),
    ]);

    return { items, total };
  }

  async findAllForExport(
    customerId?: bigint,
    dateFrom?: Date,
    dateTo?: Date,
    search?: string
  ) {
    const { items } = await this.findAll(
      undefined,
      undefined,
      customerId,
      dateFrom,
      dateTo,
      search
    );

    return items;
  }

  async findById(id: bigint) {
    return prisma.customerReceipt.findFirst({
      where: { id, deletedAt: null },
      include: {
        customer: { select: { name: true, outstandingBalance: true } },
        createdByUser: { select: { name: true } },
      },
    });
  }
}
