/**
 * MercadoPago Controller
 *
 * Endpoints para pagos con MercadoPago
 */

import { Router, Request, Response, NextFunction } from 'express';
import { DataSource } from 'typeorm';
import { MercadoPagoService } from '../services/mercadopago.service';

export class MercadoPagoController {
  public router: Router;
  private mercadoPagoService: MercadoPagoService;

  constructor(private dataSource: DataSource) {
    this.router = Router();
    this.mercadoPagoService = new MercadoPagoService(dataSource);
    this.initializeRoutes();
  }

  private initializeRoutes(): void {
    // Pagos
    this.router.post('/payments', this.createPayment.bind(this));
    this.router.get('/payments/:id', this.getPayment.bind(this));
    this.router.post('/payments/:id/refund', this.refundPayment.bind(this));

    // Links de pago
    this.router.post('/links', this.createPaymentLink.bind(this));
  }

  /**
   * POST /mercadopago/payments
   * Crear un nuevo pago
   */
  private async createPayment(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = this.getTenantId(req);
      const userId = this.getUserId(req);

      const payment = await this.mercadoPagoService.createPayment(
        tenantId,
        {
          amount: req.body.amount,
          currency: req.body.currency,
          description: req.body.description,
          paymentMethod: req.body.paymentMethod,
          customerEmail: req.body.customerEmail,
          customerName: req.body.customerName,
          referenceType: req.body.referenceType,
          referenceId: req.body.referenceId,
          metadata: req.body.metadata,
        },
        userId
      );

      res.status(201).json({
        success: true,
        data: this.sanitizePayment(payment),
      });
    } catch (error) {
      next(error);
    }
  }

  /**
   * GET /mercadopago/payments/:id
   * Obtener estado de un pago
   */
  private async getPayment(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = this.getTenantId(req);
      const paymentId = req.params.id;

      const payment = await this.mercadoPagoService.getPayment(tenantId, paymentId);

      res.json({
        success: true,
        data: this.sanitizePayment(payment),
      });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /mercadopago/payments/:id/refund
   * Reembolsar un pago
   */
  private async refundPayment(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = this.getTenantId(req);
      const paymentId = req.params.id;

      const payment = await this.mercadoPagoService.refundPayment(tenantId, {
        paymentId,
        amount: req.body.amount,
        reason: req.body.reason,
      });

      res.json({
        success: true,
        data: this.sanitizePayment(payment),
      });
    } catch (error) {
      next(error);
    }
  }

  /**
   * POST /mercadopago/links
   * Crear un link de pago
   */
  private async createPaymentLink(req: Request, res: Response, next: NextFunction): Promise<void> {
    try {
      const tenantId = this.getTenantId(req);
      const userId = this.getUserId(req);

      const link = await this.mercadoPagoService.createPaymentLink(
        tenantId,
        {
          amount: req.body.amount,
          title: req.body.title,
          description: req.body.description,
          expiresAt: req.body.expiresAt ? new Date(req.body.expiresAt) : undefined,
          referenceType: req.body.referenceType,
          referenceId: req.body.referenceId,
        },
        userId
      );

      res.status(201).json({
        success: true,
        data: link,
      });
    } catch (error) {
      next(error);
    }
  }

  /**
   * Obtener tenant ID del request
   */
  private getTenantId(req: Request): string {
    const tenantId = (req as any).tenantId || (req as any).user?.tenantId;
    if (!tenantId) {
      throw new Error('Tenant ID not found in request');
    }
    return tenantId;
  }

  /**
   * Obtener user ID del request
   */
  private getUserId(req: Request): string | undefined {
    return (req as any).userId || (req as any).user?.id;
  }

  /**
   * Sanitizar pago para respuesta (ocultar datos sensibles)
   */
  private sanitizePayment(payment: any): any {
    const { providerResponse, ...safe } = payment;
    return safe;
  }
}
