import { Request, Response } from 'express';
import { PaymentService } from '../services/payment.service';
import { sendSuccess, sendError } from '../../../utils/response.utils';
import { AuthenticatedRequest } from '../../../middleware/auth.middleware';
import prisma from '../../../config/database';
import { logger } from '../../../config/logger';

// 1. Create Payment Order / Checkout Session
export const createPayment = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { orderId, gateway, method } = req.body;
    const userId = req.user?.userId;

    if (!userId) return sendError(res, 'Unauthenticated', null, 401);

    const paymentDetails = await PaymentService.initiatePayment(orderId, gateway, userId, method);
    return sendSuccess(res, 'Payment checkout session created', paymentDetails);
  } catch (error: any) {
    logger.error('Failed to initiate payment:', error);
    return sendError(res, 'Payment initiation failed', error.message, 500);
  }
};

// 2. Verify Payment (Server-side check)
export const verifyPayment = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { orderId, payload } = req.body;
    const verification = await PaymentService.verifyPayment(orderId, payload);
    return sendSuccess(res, 'Payment verification response', verification);
  } catch (error: any) {
    logger.error('Payment verification failed:', error);
    return sendError(res, 'Payment verification failed', error.message, 500);
  }
};

// 3. Process Refund (Admin)
export const refundPayment = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { paymentId, amount, reason } = req.body;
    const result = await PaymentService.processRefund(paymentId, amount, reason);
    return sendSuccess(res, 'Refund processed successfully', result);
  } catch (error: any) {
    logger.error('Refund processing failed:', error);
    return sendError(res, 'Refund processing failed', error.message, 500);
  }
};

// 4. Retry Failed Payment
export const retryPayment = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { orderId, gateway } = req.body;
    const userId = req.user?.userId;
    if (!userId) return sendError(res, 'Unauthenticated', null, 401);

    const paymentDetails = await PaymentService.initiatePayment(orderId, gateway, userId);
    return sendSuccess(res, 'Payment retry order initiated', paymentDetails);
  } catch (error: any) {
    return sendError(res, 'Payment retry failed', error.message, 500);
  }
};

// 5. Cancel Payment Session
export const cancelPayment = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { paymentId } = req.body;
    await prisma.payment.update({
      where: { id: paymentId },
      data: { status: 'CANCELLED' },
    });
    return sendSuccess(res, 'Payment session cancelled');
  } catch (error: any) {
    return sendError(res, 'Cancellation failed', error.message, 500);
  }
};

// 6. Get Payment History (Current User)
export const getPaymentHistory = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const userId = req.user?.userId;
    const history = await prisma.payment.findMany({
      where: { userId },
      include: { order: true },
      orderBy: { createdAt: 'desc' },
    });
    return sendSuccess(res, 'Payment history retrieved', { history });
  } catch (error: any) {
    return sendError(res, 'Failed to fetch payment history', error.message, 500);
  }
};

// 7. Get All Payments Log (Admin)
export const getPayments = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const payments = await prisma.payment.findMany({
      include: {
        user: true,
        order: true,
      },
      orderBy: { createdAt: 'desc' },
      take: 100,
    });
    return sendSuccess(res, 'All payments retrieved', { payments });
  } catch (error: any) {
    return sendError(res, 'Failed to fetch payments log', error.message, 500);
  }
};

// 8. Get Single Payment Details
export const getPaymentById = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    const payment = await prisma.payment.findUnique({
      where: { id },
      include: {
        order: true,
        attempts: true,
        transactions: true,
        refunds: true,
        invoices: true,
      },
    });
    if (!payment) return sendError(res, 'Payment not found', null, 404);
    return sendSuccess(res, 'Payment details retrieved', { payment });
  } catch (error: any) {
    return sendError(res, 'Failed to fetch payment details', error.message, 500);
  }
};

// 9. Check Payment Status
export const getPaymentStatus = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    const payment = await prisma.payment.findUnique({
      where: { id },
      select: { status: true, gatewayPaymentId: true, gatewayTransactionId: true },
    });
    if (!payment) return sendError(res, 'Payment not found', null, 404);
    return sendSuccess(res, 'Payment status checked', payment);
  } catch (error: any) {
    return sendError(res, 'Status fetch failed', error.message, 500);
  }
};

// 10. Unified Gateway Callbacks
export const handleGatewayCallback = async (req: Request, res: Response) => {
  try {
    const { gateway } = req.params;
    const payload = { ...req.query, ...req.body };

    logger.info(`Received callback from gateway: ${gateway}`);
    // Respond with redirect to frontend payment success/failure page
    return res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/payment/status?gateway=${gateway}&status=success`);
  } catch (error: any) {
    logger.error('Callback error:', error);
    return res.redirect(`${process.env.FRONTEND_URL || 'http://localhost:3000'}/payment/status?status=failed`);
  }
};

// 11. Unified Gateway Webhooks
export const handleGatewayWebhook = async (req: Request, res: Response) => {
  try {
    const { gateway } = req.params;
    const signature = (req.headers['x-razorpay-signature'] ||
      req.headers['stripe-signature'] ||
      req.headers['x-verify']) as string;

    const result = await PaymentService.handleWebhook(gateway, req.body, signature);
    return res.status(200).json({ status: 'ok', result });
  } catch (error: any) {
    logger.error(`Webhook handling failed for ${req.params.gateway}:`, error);
    return res.status(500).json({ status: 'error', message: error.message });
  }
};

// 12. Download Tax Invoice Receipt
export const downloadInvoice = async (req: Request, res: Response) => {
  try {
    const { invoiceNumber } = req.params;
    const invoice = await prisma.invoice.findUnique({
      where: { invoiceNumber },
      include: { payment: { include: { order: { include: { user: true, shippingAddress: true, items: { include: { book: true } } } } } } },
    });

    if (!invoice) return sendError(res, 'Invoice not found', null, 404);

    // Mock PDF buffer response representing the generated official PDF tax invoice
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader('Content-Disposition', `attachment; filename=invoice_${invoiceNumber}.pdf`);

    const mockPdfBuffer = Buffer.from('%PDF-1.4 Mock Tax Invoice PDF Content representing Indian Books Worldwide');
    return res.status(200).send(mockPdfBuffer);
  } catch (error: any) {
    return sendError(res, 'Invoice download failed', error.message, 500);
  }
};
