import { NextRequest, NextResponse } from "next/server";
import { requireStaffAuth } from "@/lib/staff-auth";
import { prisma } from "@/lib/db";
import { getRefund } from "@/lib/stripe";
import { logger } from "@/lib/logger";
import { getDataSource } from "@/lib/data-source";
import { convexQuery, convexMutation } from "@/lib/convex-client";

/**
 * GET /api/staff/dashboard/refunds/[id]
 * Get refund details by ID
 */
export async function GET(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    const user = await requireStaffAuth();
    if (!user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const { id } = await params;

    // --- Convex path ---
    if (getDataSource("billing") === "convex") {
      try {
        const refund = (await convexQuery(
          (api.billing.queries as any).getRefundById,
          { refundId: id },
        )) as any;

        if (!refund) {
          return NextResponse.json(
            { error: "Refund not found" },
            { status: 404 },
          );
        }

        // Optionally fetch latest status from Stripe
        let stripeRefundData = null;
        try {
          stripeRefundData = await getRefund(refund.stripeRefundId);
        } catch (stripeError) {
          logger.warn("Could not fetch Stripe refund data", {
            stripeRefundId: refund.stripeRefundId,
          });
        }

        const transformedRefund = {
          id: refund._id ?? refund.id,
          stripeRefundId: refund.stripeRefundId,
          stripePaymentIntentId: refund.stripePaymentIntentId,
          stripeChargeId: refund.stripeChargeId,
          customerId: refund.customerId,
          userId: refund.userId,
          amount: refund.amount,
          amountFormatted: (refund.amount / 100).toFixed(2),
          currency: refund.currency,
          status: refund.status,
          reason: refund.reason,
          stripeReason: refund.stripeReason,
          staffId: refund.staffId,
          staffNotes: refund.staffNotes,
          customerReason: refund.customerReason,
          failureReason: refund.failureReason,
          createdAt: refund.createdAt
            ? new Date(refund.createdAt).toISOString()
            : null,
          updatedAt: refund.updatedAt
            ? new Date(refund.updatedAt).toISOString()
            : null,
          processedAt: refund.processedAt
            ? new Date(refund.processedAt).toISOString()
            : null,
          user: null,
          subscription: null,
          payment: null,
          stripeData: stripeRefundData
            ? {
                status: stripeRefundData.status,
                created: new Date(
                  stripeRefundData.created * 1000,
                ).toISOString(),
                receiptNumber: stripeRefundData.receipt_number,
                failureReason: stripeRefundData.failure_reason,
              }
            : null,
        };

        return NextResponse.json({ refund: transformedRefund });
      } catch (convexErr) {
        console.error(
          "Convex refund detail failed, falling back to Prisma:",
          convexErr,
        );
      }
    }

    // --- Prisma path ---
    // First try to find by our internal ID
    let refund = await prisma.refunds.findUnique({
      where: { id },
      include: {
        users: {
          select: {
            id: true,
            email: true,
            name: true,
            companyName: true,
            phoneNumber: true,
          },
        },
        subscriptions: {
          select: {
            id: true,
            tierId: true,
            status: true,
            billingPeriod: true,
            stripeSubscriptionId: true,
          },
        },
        payments: {
          select: {
            id: true,
            amount: true,
            currency: true,
            status: true,
            succeededAt: true,
          },
        },
      },
    });

    // If not found by internal ID, try by Stripe refund ID
    if (!refund) {
      refund = await prisma.refunds.findUnique({
        where: { stripeRefundId: id },
        include: {
          users: {
            select: {
              id: true,
              email: true,
              name: true,
              companyName: true,
              phoneNumber: true,
            },
          },
          subscriptions: {
            select: {
              id: true,
              tierId: true,
              status: true,
              billingPeriod: true,
              stripeSubscriptionId: true,
            },
          },
          payments: {
            select: {
              id: true,
              amount: true,
              currency: true,
              status: true,
              succeededAt: true,
            },
          },
        },
      });
    }

    if (!refund) {
      return NextResponse.json({ error: "Refund not found" }, { status: 404 });
    }

    // Optionally fetch latest status from Stripe
    let stripeRefundData = null;
    try {
      stripeRefundData = await getRefund(refund.stripeRefundId);
    } catch (stripeError) {
      logger.warn("Could not fetch Stripe refund data", {
        stripeRefundId: refund.stripeRefundId,
      });
    }

    // Transform for frontend
    const transformedRefund = {
      id: refund.id,
      stripeRefundId: refund.stripeRefundId,
      stripePaymentIntentId: refund.stripePaymentIntentId,
      stripeChargeId: refund.stripeChargeId,
      customerId: refund.customerId,
      userId: refund.userId,
      amount: refund.amount,
      amountFormatted: (refund.amount / 100).toFixed(2),
      currency: refund.currency,
      status: refund.status,
      reason: refund.reason,
      stripeReason: refund.stripeReason,
      staffId: refund.staffId,
      staffNotes: refund.staffNotes,
      customerReason: refund.customerReason,
      failureReason: refund.failureReason,
      createdAt: refund.createdAt.toISOString(),
      updatedAt: refund.updatedAt.toISOString(),
      processedAt: refund.processedAt?.toISOString() || null,
      user: refund.users
        ? {
            id: refund.users.id,
            email: refund.users.email,
            name: refund.users.name,
            companyName: refund.users.companyName,
            phoneNumber: refund.users.phoneNumber,
          }
        : null,
      subscription: refund.subscriptions
        ? {
            id: refund.subscriptions.id,
            tierId: refund.subscriptions.tierId,
            status: refund.subscriptions.status,
            billingPeriod: refund.subscriptions.billingPeriod,
            stripeSubscriptionId: refund.subscriptions.stripeSubscriptionId,
          }
        : null,
      payment: refund.payments
        ? {
            id: refund.payments.id,
            amount: refund.payments.amount,
            currency: refund.payments.currency,
            status: refund.payments.status,
            succeededAt: refund.payments.succeededAt?.toISOString() || null,
          }
        : null,
      // Include Stripe's latest data if available
      stripeData: stripeRefundData
        ? {
            status: stripeRefundData.status,
            created: new Date(stripeRefundData.created * 1000).toISOString(),
            receiptNumber: stripeRefundData.receipt_number,
            failureReason: stripeRefundData.failure_reason,
          }
        : null,
    };

    return NextResponse.json({ refund: transformedRefund });
  } catch (error) {
    logger.error("Failed to fetch refund:", { error });
    return NextResponse.json(
      { error: "Failed to fetch refund" },
      { status: 500 },
    );
  }
}

/**
 * PATCH /api/staff/dashboard/refunds/[id]
 * Update refund notes (staff can only update notes, not refund itself)
 */
export async function PATCH(
  request: NextRequest,
  { params }: { params: Promise<{ id: string }> },
) {
  try {
    const user = await requireStaffAuth();
    if (!user) {
      return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
    }

    const { id } = await params;
    const body = await request.json();
    const { staffNotes } = body;

    // --- Convex path ---
    if (getDataSource("billing") === "convex") {
      try {
        await convexMutation((api.billing.mutations as any).updateRefundNotes, {
          refundId: id,
          staffNotes: staffNotes ?? "",
        });

        logger.info("Refund notes updated via Convex", {
          refundId: id,
          staffId: user.id,
        });

        return NextResponse.json({
          success: true,
          refund: {
            id,
            staffNotes,
            updatedAt: new Date().toISOString(),
          },
        });
      } catch (convexErr) {
        console.error(
          "Convex refund notes update failed, falling back to Prisma:",
          convexErr,
        );
      }
    }

    // --- Prisma path ---
    // Find the refund
    const refund = await prisma.refunds.findUnique({
      where: { id },
    });

    if (!refund) {
      return NextResponse.json({ error: "Refund not found" }, { status: 404 });
    }

    // Update only allowed fields (staff notes)
    const updatedRefund = await prisma.refunds.update({
      where: { id },
      data: {
        staffNotes: staffNotes !== undefined ? staffNotes : refund.staffNotes,
      },
    });

    logger.info("Refund notes updated", {
      refundId: id,
      staffId: user.id,
    });

    return NextResponse.json({
      success: true,
      refund: {
        id: updatedRefund.id,
        staffNotes: updatedRefund.staffNotes,
        updatedAt: updatedRefund.updatedAt.toISOString(),
      },
    });
  } catch (error) {
    logger.error("Failed to update refund:", { error });
    return NextResponse.json(
      { error: "Failed to update refund" },
      { status: 500 },
    );
  }
}
