import { Router } from "express";
import { checkAuth } from "../middleware/checkAuth";
import {
  getWallet,
  listWalletTransactions,
  createWalletTopUpIntent,
  reconcileWalletTopUp,
  reconcileWalletBalanceEndpoint,
  requestWalletWithdrawal,
  listWalletPaymentMethods,
  detachWalletPaymentMethod,
  connectWalletStripe,
  refreshWalletStripeStatus,
  walletStripeConnectReturnPage,
  walletStripeConnectRefreshPage,
} from "../controllers/walletController";

const router = Router();

router.get("/stripe/return", walletStripeConnectReturnPage);
router.get("/stripe/refresh", walletStripeConnectRefreshPage);

router.get("/", checkAuth, getWallet);
router.get("/transactions", checkAuth, listWalletTransactions);
router.get("/payment-methods", checkAuth, listWalletPaymentMethods);
router.delete(
  "/payment-methods/:paymentMethodId",
  checkAuth,
  detachWalletPaymentMethod
);
router.post("/top-up/intent", checkAuth, createWalletTopUpIntent);
router.post("/top-up/reconcile", checkAuth, reconcileWalletTopUp);
router.post("/reconcile-balance", checkAuth, reconcileWalletBalanceEndpoint);
router.post("/withdraw", checkAuth, requestWalletWithdrawal);
router.post("/connect-stripe", checkAuth, connectWalletStripe);
router.post("/refresh-stripe-status", checkAuth, refreshWalletStripeStatus);

export default router;

/**
 * @swagger
 * tags:
 *   name: Wallet
 *   description: |
 *     App user wallet (USD cents). Top-up uses a Stripe Customer plus PaymentIntent; confirm in the app with clientSecret from the API.
 *     New cards can be saved for reuse (on_session). List or remove cards using GET and DELETE on wallet/payment-methods.
 *     Balance is credited when Stripe sends payment_intent.succeeded to the wallet stripe-webhook endpoint (see app registration).
 *     If the balance stays 0 after a successful card payment, call **POST** `/wallet/top-up/reconcile` with **paymentIntentId** (webhook may be unreachable).
 *     For bank payouts (Stripe Connect), set **returnUrl** to **GET** `/user/stripe/return` (preferred) or `/wallet/stripe/return`, and **refreshUrl** to **GET** `/user/stripe/refresh` or `/wallet/stripe/refresh` (API appends `uid`). Mobile can call **POST** `/user/refresh-stripe-status` or `/wallet/refresh-stripe-status` with Bearer after a deep link.
 */

/**
 * @swagger
 * /api/v1/wallet:
 *   get:
 *     summary: Get available wallet balance
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Current balance
 *       401:
 *         description: Unauthorized
 */

/**
 * @swagger
 * /api/v1/wallet/transactions:
 *   get:
 *     summary: Paginated wallet transaction history
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: query
 *         name: page
 *         schema:
 *           type: integer
 *           default: 1
 *       - in: query
 *         name: limit
 *         schema:
 *           type: integer
 *           default: 20
 *       - in: query
 *         name: type
 *         description: Filter by transaction type
 *         schema:
 *           type: string
 *           enum: [topup, payment_debit, withdrawal, withdrawal_reversal, refund, adjustment]
 *     responses:
 *       200:
 *         description: List of transactions
 *       401:
 *         description: Unauthorized
 */

/**
 * @swagger
 * /api/v1/wallet/payment-methods:
 *   get:
 *     summary: List saved cards (Stripe PaymentMethods) for wallet top-up
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Empty array until first top-up creates a Stripe Customer
 *       401:
 *         description: Unauthorized
 */

/**
 * @swagger
 * /api/v1/wallet/payment-methods/{paymentMethodId}:
 *   delete:
 *     summary: Remove a saved card from this wallet
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     parameters:
 *       - in: path
 *         name: paymentMethodId
 *         required: true
 *         schema:
 *           type: string
 *           example: pm_123
 *     responses:
 *       200:
 *         description: Card detached
 *       400:
 *         description: Invalid id
 *       403:
 *         description: Not your payment method
 *       401:
 *         description: Unauthorized
 */

/**
 * @swagger
 * /api/v1/wallet/top-up/intent:
 *   post:
 *     summary: Create Stripe PaymentIntent for wallet top-up (mobile SDK)
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - amountCents
 *             properties:
 *               amountCents:
 *                 type: integer
 *                 minimum: 100
 *                 description: Amount in USD cents (minimum $1; no maximum)
 *                 example: 1000
 *               currency:
 *                 type: string
 *                 enum: [usd]
 *                 default: usd
 *               paymentMethodId:
 *                 type: string
 *                 description: Optional saved card id from GET /wallet/payment-methods (pm_…)
 *                 example: pm_1ABC
 *     responses:
 *       200:
 *         description: Returns clientSecret, publishableKey, stripeCustomerId; new cards saved for reuse (on_session)
 *       400:
 *         description: Validation error or Stripe not configured
 *       401:
 *         description: Unauthorized
 *       403:
 *         description: Account suspended
 */

/**
 * @swagger
 * /api/v1/wallet/reconcile-balance:
 *   post:
 *     summary: Force a balance reconciliation (fix stale or under-credited balance)
 *     tags: [Wallet]
 *     description: |
 *       Pulls succeeded PaymentIntents from Stripe, recovers any stale "processing" ledger rows,
 *       and sets walletBalanceCents = max(0, sum of completed deltaCents) when under-credited.
 *       Idempotent — safe to call multiple times. Use when /wallet shows a stale balance after a successful top-up.
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: Returns balance, previousBalance, expectedBalance and amount corrected
 *       401:
 *         description: Unauthorized
 *       403:
 *         description: Account suspended
 */

/**
 * @swagger
 * /api/v1/wallet/withdraw:
 *   post:
 *     summary: Withdraw from wallet (ledger debit; external payout separate)
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - amountCents
 *             properties:
 *               amountCents:
 *                 type: integer
 *                 minimum: 1
 *                 description: Minimum 500 cents ($5) enforced by API
 *                 example: 500
 *               note:
 *                 type: string
 *                 maxLength: 500
 *     responses:
 *       200:
 *         description: Withdrawal recorded
 *       400:
 *         description: Insufficient balance or validation error
 *       401:
 *         description: Unauthorized
 */

/**
 * @swagger
 * /api/v1/wallet/stripe/return:
 *   get:
 *     summary: Stripe Connect return callback (public HTML; syncs app user Connect)
 *     tags: [Wallet]
 *     description: |
 *       Use this URL (with optional query; server adds **uid** when creating account links) as **returnUrl** in POST /wallet/connect-stripe.
 *       Reads **uid** (Mongo user id), updates Stripe flags on User, returns a short HTML confirmation.
 *     parameters:
 *       - in: query
 *         name: uid
 *         required: true
 *         schema:
 *           type: string
 *         description: User id (added automatically by connect-stripe)
 *     responses:
 *       200:
 *         description: HTML page
 *       400:
 *         description: Missing uid
 */

/**
 * @swagger
 * /api/v1/wallet/stripe/refresh:
 *   get:
 *     summary: Stripe Connect refresh callback (public HTML)
 *     tags: [Wallet]
 *     description: Use as **refreshUrl** in POST /wallet/connect-stripe when the onboarding link expires.
 *     parameters:
 *       - in: query
 *         name: uid
 *         required: true
 *         schema:
 *           type: string
 *     responses:
 *       200:
 *         description: HTML page
 *       400:
 *         description: Missing uid
 */

/**
 * @swagger
 * /api/v1/wallet/connect-stripe:
 *   post:
 *     summary: Stripe Connect onboarding link (Express) for app user payouts
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *             required:
 *               - returnUrl
 *               - refreshUrl
 *             properties:
 *               returnUrl:
 *                 type: string
 *                 format: uri
 *               refreshUrl:
 *                 type: string
 *                 format: uri
 *     responses:
 *       200:
 *         description: Returns url to open for Stripe Connect onboarding
 *       401:
 *         description: Unauthorized
 */

/**
 * @swagger
 * /api/v1/wallet/refresh-stripe-status:
 *   post:
 *     summary: Sync Stripe Connect status after user returns from onboarding
 *     tags: [Wallet]
 *     security:
 *       - bearerAuth: []
 *     responses:
 *       200:
 *         description: stripeConnected, stripeChargesEnabled, stripeDetailsSubmitted, stripeStatus
 *       401:
 *         description: Unauthorized
 */

/**
 * @swagger
 * /api/v1/wallet/stripe-webhook:
 *   post:
 *     summary: Stripe webhook (raw JSON body, Stripe-Signature) — credits wallet on successful payment
 *     tags: [Wallet]
 *     description: |
 *       Not called from mobile apps. Configure in Stripe Dashboard (payment_intent.succeeded).
 *       Server must receive **raw** body; uses STRIPE_WEBHOOK_SECRET.
 *     requestBody:
 *       required: true
 *       content:
 *         application/json:
 *           schema:
 *             type: object
 *     responses:
 *       200:
 *         description: Event received
 *       400:
 *         description: Invalid signature or payload
 *       503:
 *         description: Webhook secret not configured
 */
