import { NextRequest } from "next/server";
import { AffiliateAccountStatus } 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 updateAccountSchema = z.object({
  accountId: z.string().uuid(),
  status: z.nativeEnum(AffiliateAccountStatus).optional(),
  defaultOfferId: z.string().uuid().nullable().optional(),
  managerNote: z.string().max(1200).nullable().optional()
});

export async function GET(request: NextRequest) {
  try {
    await requireAffiliateAdmin(request);
    const accounts = await prisma.affiliateAccount.findMany({
      orderBy: { createdAt: "desc" },
      take: 100,
      include: { user: true, defaultOffer: true }
    });

    return ok({
      accounts: accounts.map((account) => ({
        id: account.id,
        publicId: account.publicId,
        displayName: account.displayName,
        companyName: account.companyName,
        website: account.website,
        country: account.country,
        status: account.status,
        payoutMethod: account.payoutMethod,
        managerNote: account.managerNote,
        createdAt: account.createdAt,
        approvedAt: account.approvedAt,
        email: account.user.email,
        offer: account.defaultOffer
          ? {
              id: account.defaultOffer.id,
              code: account.defaultOffer.code,
              name: account.defaultOffer.name,
              type: account.defaultOffer.type,
              status: account.defaultOffer.status
            }
          : null
      }))
    });
  } catch (error) {
    return fail(error);
  }
}

export async function PATCH(request: NextRequest) {
  try {
    await requireAffiliateAdmin(request);
    const input = await parseJson(request, updateAccountSchema);
    const account = await prisma.affiliateAccount.update({
      where: { id: input.accountId },
      data: {
        status: input.status,
        defaultOfferId: input.defaultOfferId,
        managerNote: input.managerNote,
        approvedAt: input.status === AffiliateAccountStatus.ACTIVE ? new Date() : undefined
      },
      include: { defaultOffer: true, user: true }
    });

    return ok({
      account: {
        id: account.id,
        status: account.status,
        approvedAt: account.approvedAt,
        offer: account.defaultOffer ? { id: account.defaultOffer.id, code: account.defaultOffer.code, name: account.defaultOffer.name } : null
      }
    });
  } catch (error) {
    return fail(error);
  }
}
