import { prisma } from "@/lib/prisma";
import { Prisma } from "@/app/generated/prisma/client";
import type { PayoutStatus } from "@/app/generated/prisma/enums";

const payoutListInclude = {
  booking: {
    select: {
      id: true,
      amount: true,
      status: true,
      user: { select: { id: true, name: true, email: true } },
    },
  },
  trip: {
    select: { id: true, title: true, date: true, endDate: true, status: true },
  },
  organizer: { select: { id: true, name: true, email: true } },
  processedBy: { select: { id: true, name: true, email: true } },
} satisfies Prisma.PayoutInclude;

export const payoutRepo = {
  async findById(id: string) {
    return prisma.payout.findUnique({
      where: { id },
      include: payoutListInclude,
    });
  },

  async findByBookingId(bookingId: string, tx?: Prisma.TransactionClient) {
    const client = tx ?? prisma;
    return client.payout.findUnique({ where: { bookingId } });
  },

  async listByStatus(
    status: PayoutStatus,
    filters?: {
      dateFrom?: Date;
      dateTo?: Date;
      processorEmail?: string;
    }
  ) {
    const where: Prisma.PayoutWhereInput = { status };
    if (filters?.dateFrom || filters?.dateTo) {
      where.createdAt = {
        ...(filters.dateFrom && { gte: filters.dateFrom }),
        ...(filters.dateTo && { lte: filters.dateTo }),
      };
    }
    if (filters?.processorEmail) {
      where.processedBy = { email: filters.processorEmail };
    }
    return prisma.payout.findMany({
      where,
      orderBy: { heldUntil: "asc" },
      include: payoutListInclude,
    });
  },

  async listForOrganizer(organizerId: string) {
    return prisma.payout.findMany({
      where: { organizerId },
      orderBy: { createdAt: "desc" },
      include: {
        trip: {
          select: { id: true, title: true, date: true, endDate: true, status: true },
        },
        booking: {
          select: {
            id: true,
            amount: true,
            user: { select: { id: true, name: true } },
          },
        },
      },
    });
  },

  async countByStatus(status: PayoutStatus) {
    return prisma.payout.count({ where: { status } });
  },

  /** Payout terbaru untuk satu status — dipakai dashboard admin. */
  async listRecent(status: PayoutStatus, limit = 3) {
    return prisma.payout.findMany({
      where: { status },
      orderBy: status === "HELD" ? { heldUntil: "asc" } : { updatedAt: "desc" },
      take: limit,
      select: {
        id: true,
        amount: true,
        heldUntil: true,
        releasedAt: true,
        organizer: { select: { id: true, name: true } },
        trip: { select: { id: true, title: true } },
      },
    });
  },

  async create(
    data: Pick<
      Prisma.PayoutUncheckedCreateInput,
      | "bookingId"
      | "tripId"
      | "organizerId"
      | "amount"
      | "heldUntil"
      | "bankName"
      | "bankAccountNumber"
      | "bankAccountName"
    >,
    tx?: Prisma.TransactionClient
  ) {
    const client = tx ?? prisma;
    return client.payout.create({ data });
  },

  async update(
    id: string,
    data: Prisma.PayoutUncheckedUpdateInput,
    tx?: Prisma.TransactionClient
  ) {
    const client = tx ?? prisma;
    return client.payout.update({ where: { id }, data });
  },

  /** Cari semua HELD payout yang sudah lewat heldUntil & trip-nya COMPLETED. */
  async findEligibleForRelease(now: Date) {
    return prisma.payout.findMany({
      where: {
        status: "HELD",
        heldUntil: { lte: now },
        trip: { status: "COMPLETED" },
      },
      select: { id: true },
    });
  },
};

export type PayoutWithRelations = Awaited<ReturnType<typeof payoutRepo.findById>>;
