import type { Express, Request, Response } from "express";
import { createPayment } from "../services/squarePaymentService.ts";
import { creditWallet, writeAuditLog, getCoinPackages, getUserById } from "../db.ts";

/**
 * Register Square payment endpoint
 */
export function registerSquarePaymentRoutes(app: Express) {
  // Create payment endpoint
  app.post("/api/square/create-payment", async (req: Request, res: Response) => {
    try {
      const { amount, currency, packageId, packageName, paymentMethod } = req.body;

      // Validate input
      if (!amount || !currency || !packageId) {
        return res.status(400).json({
          success: false,
          error: "Missing required fields: amount, currency, packageId",
        });
      }

      // Get user from session
      const userId = (req as any).user?.id;
      if (!userId) {
        return res.status(401).json({
          success: false,
          error: "Unauthorized",
        });
      }

      // Fetch package details
      const packages = await getCoinPackages();
      const pkg = packages.find(p => p.id === packageId);
      if (!pkg || !pkg.isActive) {
        return res.status(404).json({
          success: false,
          error: "Package not found or inactive",
        });
      }

      // Verify amount matches package price
      const expectedAmount = parseFloat(pkg.priceUsd);
      if (Math.abs(amount - expectedAmount) > 0.01) {
        return res.status(400).json({
          success: false,
          error: "Amount mismatch",
        });
      }

      // Generate idempotency key
      const idempotencyKey = `square-${userId}-${packageId}-${Date.now()}`;

      // For now, we'll simulate the payment since we need the actual payment method token
      // In production, the frontend would use Square Web Payments SDK to tokenize the card
      // and send us the sourceId/nonce
      const sourceId = req.body.sourceId || "cnon:card-nonce-ok"; // Mock token for testing

      // Create payment via Square API
      const paymentResult = await createPayment({
        sourceId,
        amount: Math.round(amount * 100), // Convert to cents
        currency: currency.toUpperCase(),
        idempotencyKey,
        customerId: userId.toString(),
        referenceId: packageId.toString(),
        note: `Purchase: ${packageName}`,
      });

      if (!paymentResult.success) {
        console.error("[Square] Payment failed:", paymentResult.error);
        return res.status(400).json({
          success: false,
          error: paymentResult.error || "Payment processing failed",
        });
      }

      // Credit user's wallet
      const gcAmount = parseInt(pkg.gcAmount);
      const scBonus = parseFloat(pkg.scBonusAmount);

      try {
        // Credit gold coins
        await creditWallet(
          userId,
          "GC",
          gcAmount,
          "gc_purchase",
          `Coin package purchase (${packageName})`,
          "square"
        );

        // Credit bonus SC if any
        if (scBonus > 0) {
          await creditWallet(
            userId,
            "SC",
            scBonus,
            "sc_bonus",
            `Bonus SC from ${packageName}`,
            "square"
          );
        }

        // Log the payment
        await writeAuditLog({
          actorId: userId,
          actorRole: "user",
          targetUserId: userId,
          action: "payment_completed",
          category: "wallet",
          details: {
            packageId,
            packageName,
            gcAmount,
            scBonus,
            paymentId: paymentResult.paymentId,
            paymentMethod,
            amount,
            currency,
          },
        });

        console.log(
          `[Square] Credited ${gcAmount} GC${scBonus > 0 ? ` + ${scBonus} SC` : ""} to user ${userId}`
        );

        // Return success response with serialized data
        return res.json({
          success: true,
          paymentId: paymentResult.paymentId,
          status: paymentResult.status,
          message: "Payment successful",
        });
      } catch (creditError: any) {
        console.error(`[Square] Failed to credit user ${userId}:`, creditError.message);
        // Still return success since payment was processed
        return res.json({
          success: true,
          paymentId: paymentResult.paymentId,
          status: paymentResult.status,
          message: "Payment processed but wallet credit pending",
        });
      }
    } catch (error: any) {
      console.error("[Square] Endpoint error:", error.message);
      return res.status(500).json({
        success: false,
        error: error.message || "Internal server error",
      });
    }
  });

  // Get payment status endpoint
  app.get("/api/square/payment/:paymentId", async (req: Request, res: Response) => {
    try {
      const { paymentId } = req.params;

      if (!paymentId) {
        return res.status(400).json({
          success: false,
          error: "Payment ID required",
        });
      }

      // Get user from session
      const userId = (req as any).user?.id;
      if (!userId) {
        return res.status(401).json({
          success: false,
          error: "Unauthorized",
        });
      }

      // In production, you would fetch the actual payment from Square
      // For now, return a mock response
      return res.json({
        success: true,
        paymentId,
        status: "completed",
        message: "Payment status retrieved",
      });
    } catch (error: any) {
      console.error("[Square] Get payment error:", error.message);
      return res.status(500).json({
        success: false,
        error: error.message || "Internal server error",
      });
    }
  });
}
