import { NextRequest } from "next/server";
import { AffiliateCommissionStatus, AffiliatePayoutStatus } from "@prisma/client";
import { z } from "zod";
import { prisma } from "@/server/db";
import { requireAffiliateAdmin } from "@/server/affiliation/service";
import { fail, ok, parseJson } from "@/server/http";

const updatePayoutSchema = z.object({
  payoutId: z.string().uuid(),
  status: z.nativeEnum(AffiliatePayoutStatus),
  paymentReference: z.string().max(160).optional().nullable(),
  adminNote: z.string().max(1200).optional().nullable()
});

export async function GET(request: NextRequest) {
  try {
    await requireAffiliateAdmin(request);
    const payouts = await prisma.affiliatePayout.findMany({
      orderBy: { createdAt: "desc" },
      take: 100,
      include: { account: true }
    });
    return ok({
      payouts: payouts.map((payout) => ({
        id: payout.id,
        affiliate: payout.account.displayName,
        periodStart: payout.periodStart,
        periodEnd: payout.periodEnd,
        amount: payout.amount.toString(),
        currency: payout.currency,
        status: payout.status,
        requestedAt: payout.requestedAt,
        approvedAt: payout.approvedAt,
        paidAt: payout.paidAt,
        paymentMethod: payout.paymentMethod,
        paymentReference: payout.paymentReference,
        adminNote: payout.adminNote
      }))
    });
  } catch (error) {
    return fail(error);
  }
}

export async function PATCH(request: NextRequest) {
  try {
    await requireAffiliateAdmin(request);
    const input = await parseJson(request, updatePayoutSchema);
    const now = new Date();
    const payout = await prisma.$transaction(async (tx) => {
      const updated = await tx.affiliatePayout.update({
        where: { id: input.payoutId },
        data: {
          status: input.status,
          approvedAt: input.status === AffiliatePayoutStatus.APPROVED ? now : undefined,
          paidAt: input.status === AffiliatePayoutStatus.PAID ? now : undefined,
          paymentReference: input.paymentReference,
          adminNote: input.adminNote
        }
      });

      if (input.status === AffiliatePayoutStatus.PAID) {
        await tx.affiliateCommission.updateMany({
          where: { payoutId: updated.id },
          data: { status: AffiliateCommissionStatus.PAID }
        });
      }

      return updated;
    });

    return ok({ payout: { id: payout.id, status: payout.status } });
  } catch (error) {
    return fail(error);
  }
}
