import express from "express";
import MerchantController from "../controllers/merchantController.js";
import CustomerController from "../controllers/customerController.js";
import TransactionController from "../controllers/transactionController.js";
import WebhookController from "../controllers/webhookController.js";
import AdminController from "../controllers/adminController.js";
import CardController from "../controllers/cardController.js";
import MerchantAuthController from "../controllers/merchantAuthController.js";
import SubscriptionController from "../controllers/subscriptionController.js";
import KybController from "../controllers/kybController.js";
import AdminKybController from "../controllers/adminKybController.js";
import {
    authenticateAdmin,
    authorizeSuperAdmin,
    authenticateMerchant,
    authenticateMerchantAPIKey,
    authenticateMerchantJWT,
    requireLiveMode
} from "../middlewares/authMiddleware.js";
import {
    loginValidation,
    merchantRegistrationValidation
} from "../validators/authValidator.js";
import {
    payoutValidation,
    customerCreationValidation,
    feeUpdateValidation,
    bvnKycValidation,
    idKycValidation,
    walletSwapValidation
} from "../validators/transactionValidator.js";
import { loginLimiter, otpLimiter } from "../middlewares/rateLimiter.js";

const router = express.Router();

// Admin Auth
router.post("/admin/login", loginLimiter, AdminController.login);
router.post("/admin/verify-otp", otpLimiter, AdminController.verifyLoginOtp);
router.post("/admin/forgot-password", otpLimiter, AdminController.forgotPassword);
router.post("/admin/reset-password", AdminController.resetPassword);
router.post("/admin/2fa/toggle", authenticateAdmin, AdminController.toggle2fa);

// Admin Exclusive Routes
router.post("/admin/merchants", authenticateAdmin, authorizeSuperAdmin, merchantRegistrationValidation, AdminController.registerMerchant);
router.get("/admin/merchants", authenticateAdmin, AdminController.getAllMerchants);
router.get("/admin/merchants/:merchantId", authenticateAdmin, AdminController.getMerchantFullProfile);
router.patch("/admin/merchants/:merchantId/status", authenticateAdmin, authorizeSuperAdmin, AdminController.updateMerchantStatus);
router.get("/admin/merchants/:merchantId/stats", authenticateAdmin, AdminController.getMerchantStatsAdmin);
router.get("/admin/profits/stats", authenticateAdmin, AdminController.getSystemProfitStats);
router.get("/admin/profits/history", authenticateAdmin, AdminController.getSystemProfitHistory);
router.get("/admin/report", authenticateAdmin, AdminController.getPlatformReport);
router.get("/admin/dashboard", authenticateAdmin, AdminController.getDashboardStats);
router.get("/admin/transactions", authenticateAdmin, AdminController.getAllTransactionsAdmin);
router.get("/admin/customers", authenticateAdmin, AdminController.getAllCustomersAdmin);
router.get("/admin/customers/:customerId", authenticateAdmin, AdminController.getCustomerFullProfile);
router.patch("/admin/customers/:customerId/status", authenticateAdmin, authorizeSuperAdmin, AdminController.updateCustomerStatus);
router.get("/admin/customers/:customerId/cards", authenticateAdmin, AdminController.getCustomerCardsAdmin);

// Admin IP Whitelist Management (SuperAdmin only)
router.get("/admin/ip-whitelist", authenticateAdmin, authorizeSuperAdmin, AdminController.getIpWhitelists);
router.post("/admin/ip-whitelist", authenticateAdmin, authorizeSuperAdmin, AdminController.addIpWhitelist);
router.patch("/admin/ip-whitelist/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.updateIpWhitelist);
router.delete("/admin/ip-whitelist/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.deleteIpWhitelist);

// Admin Card Management (Admin can manage all cards; SuperAdmin can update balances)
router.get("/admin/merchants/:merchantId/cards", authenticateAdmin, AdminController.getCardsByMerchant);
router.get("/admin/cards/:cardId", authenticateAdmin, AdminController.getCardDetailAdmin);
router.post("/admin/cards/:cardId/freeze", authenticateAdmin, AdminController.adminFreezeCard);
router.post("/admin/cards/:cardId/unfreeze", authenticateAdmin, AdminController.adminUnfreezeCard);
router.post("/admin/cards/:cardId/terminate", authenticateAdmin, authorizeSuperAdmin, AdminController.adminTerminateCard);
router.patch("/admin/cards/:cardId/balance", authenticateAdmin, authorizeSuperAdmin, AdminController.adminUpdateCardBalance);
// Admin KYB Review (SuperAdmin)
router.get("/admin/kyb", authenticateAdmin, authorizeSuperAdmin, AdminKybController.getAllApplications);
router.get("/admin/kyb/:id", authenticateAdmin, authorizeSuperAdmin, AdminKybController.getApplicationById);
router.patch("/admin/kyb/:id/status", authenticateAdmin, authorizeSuperAdmin, AdminKybController.updateStatus);

// Dynamic Fee Management (SuperAdmin only)
router.get("/admin/settings", authenticateAdmin, authorizeSuperAdmin, AdminController.getFeeSettings);
router.patch("/admin/settings", authenticateAdmin, authorizeSuperAdmin, feeUpdateValidation, AdminController.updateFeeSettings);
router.patch("/admin/merchants/:merchantId/fees", authenticateAdmin, authorizeSuperAdmin, AdminController.updateMerchantFees);
router.get("/admin/merchants/:merchantId/service-pricing", authenticateAdmin, AdminController.getMerchantServicePricing);
router.delete("/admin/merchants/:merchantId/service-pricing/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.deleteMerchantServicePricing);

// Admin KYC & System Service Management (SuperAdmin only for edits)
router.get("/admin/kyc/stages", authenticateAdmin, AdminController.getKycStages);
router.get("/admin/services", authenticateAdmin, AdminController.getSystemServices);
router.patch("/admin/services/:serviceId/status", authenticateAdmin, authorizeSuperAdmin, AdminController.toggleGlobalServiceStatus);
router.post("/admin/kyc/stages/:stageId/services", authenticateAdmin, authorizeSuperAdmin, AdminController.mapServiceToStage);
router.patch("/admin/kyc/stages/:stageId/services/:serviceId", authenticateAdmin, authorizeSuperAdmin, AdminController.toggleStageServiceStatus);

// Global Currency Management (SuperAdmin only for edits)
router.post("/admin/currencies", authenticateAdmin, authorizeSuperAdmin, AdminController.createCurrency);
router.get("/admin/currencies", authenticateAdmin, AdminController.getAllCurrencies);
router.patch("/admin/currencies/:code/status", authenticateAdmin, authorizeSuperAdmin, AdminController.updateCurrencyStatus);
router.patch("/admin/currencies/:code/virtual-account-status", authenticateAdmin, authorizeSuperAdmin, AdminController.updateCurrencyVirtualAccountStatus);

// Service Pricing Management (SuperAdmin only for edits)
router.post("/admin/service-pricing", authenticateAdmin, authorizeSuperAdmin, AdminController.createServicePricing);
router.get("/admin/service-pricing", authenticateAdmin, AdminController.getAllServicePricing);
router.patch("/admin/service-pricing/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.updateServicePricing);
router.delete("/admin/service-pricing/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.deleteServicePricing);

// Email Template Management (SuperAdmin)
router.get("/admin/email-templates", authenticateAdmin, authorizeSuperAdmin, AdminController.getEmailTemplates);
router.get("/admin/email-templates/:slug", authenticateAdmin, authorizeSuperAdmin, AdminController.getEmailTemplate);
router.patch("/admin/email-templates/:slug", authenticateAdmin, authorizeSuperAdmin, AdminController.updateEmailTemplate);

// Exchange Rate Management (SuperAdmin)
router.get("/admin/exchange-rates", authenticateAdmin, authorizeSuperAdmin, AdminController.getAllExchangeRates);
router.get("/admin/exchange-rates/preview", authenticateAdmin, authorizeSuperAdmin, AdminController.previewLiveRate);
router.post("/admin/exchange-rates", authenticateAdmin, authorizeSuperAdmin, AdminController.createExchangeRate);
router.patch("/admin/exchange-rates/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.updateExchangeRate);
router.delete("/admin/exchange-rates/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.deleteExchangeRate);

// Subscription Plan Management (SuperAdmin)
router.post("/admin/subscription-plans", authenticateAdmin, authorizeSuperAdmin, AdminController.createSubscriptionPlan);
router.get("/admin/subscription-plans", authenticateAdmin, AdminController.getAllSubscriptionPlans);
router.patch("/admin/subscription-plans/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.updateSubscriptionPlan);
router.delete("/admin/subscription-plans/:id", authenticateAdmin, authorizeSuperAdmin, AdminController.deleteSubscriptionPlan);
router.get("/admin/subscriptions/stats", authenticateAdmin, AdminController.getSubscriptionStats);

// Merchant Auth & Key Management
router.post("/merchants/register", merchantRegistrationValidation, MerchantAuthController.register);
router.post("/merchants/login", loginLimiter, loginValidation, MerchantAuthController.login);
router.post("/merchants/verify-otp", otpLimiter, MerchantAuthController.verifyLoginOtp);
router.post("/merchants/forgot-password", otpLimiter, MerchantAuthController.forgotPassword);
router.post("/merchants/reset-password", MerchantAuthController.resetPassword);
router.post("/merchants/2fa/toggle", authenticateMerchantJWT, MerchantAuthController.toggle2fa);
router.get("/merchants/keys", authenticateMerchantJWT, MerchantAuthController.getApiKeys);
router.post("/merchants/keys/regenerate", authenticateMerchantJWT, MerchantAuthController.regenerateKeys);
router.patch("/merchants/webhook", authenticateMerchantJWT, MerchantAuthController.updateWebhookUrl);
router.patch("/merchants/profile", authenticateMerchantJWT, MerchantAuthController.updateMerchantProfile);
router.post("/merchants/payout/request-otp", authenticateMerchantJWT, MerchantController.requestPayoutOtp);

// Merchant KYB Submission
router.get("/merchants/kyb", authenticateMerchantJWT, KybController.getKybApplication);
router.put("/merchants/kyb", authenticateMerchantJWT, KybController.upsertKybApplication);
router.post("/merchants/kyb/submit", authenticateMerchantJWT, KybController.submitKybApplication);

// Merchant Subscription Routes
router.get("/merchants/subscriptions/plans", authenticateMerchantJWT, SubscriptionController.getAvailablePlans);
router.get("/merchants/subscriptions/me", authenticateMerchantJWT, SubscriptionController.getMySubscription);
router.post("/merchants/subscriptions", authenticateMerchantJWT, SubscriptionController.subscribe);
router.patch("/merchants/subscriptions/change-plan", authenticateMerchantJWT, SubscriptionController.changePlan);
router.post("/merchants/subscriptions/cancel", authenticateMerchantJWT, SubscriptionController.cancelSubscription);
router.get("/merchants/subscriptions/history", authenticateMerchantJWT, SubscriptionController.getSubscriptionHistory);
router.get("/merchants/subscriptions/invoices", authenticateMerchantJWT, SubscriptionController.getInvoices);

// Merchant Protected Resources
router.get("/merchants/me", authenticateMerchantJWT, MerchantController.getMerchantDetails);
router.get("/merchants/stats", authenticateMerchantJWT, MerchantController.getMerchantStats);
router.get("/merchants/transactions", authenticateMerchantJWT, MerchantController.getMerchantTransactions);
router.get("/merchants/customers", authenticateMerchantJWT, MerchantController.viewCustomerBalances);
router.get("/merchants/ip-whitelist", authenticateMerchantJWT, MerchantController.getIpWhitelists);
router.post("/merchants/ip-whitelist", authenticateMerchantJWT, MerchantController.addIpWhitelist);
router.delete("/merchants/ip-whitelist/:id", authenticateMerchantJWT, MerchantController.deleteIpWhitelist);
router.post("/merchants/payout", authenticateMerchant, requireLiveMode, payoutValidation, MerchantController.initiatePayout); // Payout requires approved KYB live mode
router.get("/merchants/pricing", authenticateMerchant, MerchantController.getServicePricings);
router.get("/merchants/rates", authenticateMerchant, MerchantController.getExchangeRates);
router.get("/merchants/wallets", authenticateMerchant, MerchantController.getWallets);
router.post("/merchants/wallets/swap", authenticateMerchant, walletSwapValidation, MerchantController.swapCurrency);

// Webhook Management (Merchant Dashboard)
router.get("/merchants/webhooks/outgoing", authenticateMerchantJWT, WebhookController.getOutgoingLogs);
router.post("/merchants/webhooks/outgoing/:id/resend", authenticateMerchantJWT, WebhookController.resendOutgoingWebhook);
router.get("/merchants/webhooks/incoming", authenticateMerchantJWT, WebhookController.getIncomingLogs);
router.post("/merchants/webhooks/incoming/:id/retry", authenticateMerchantJWT, WebhookController.retryIncomingWebhook);

// Customer Operations
// 1. Creation: STRICTLY via API Keys (Server-to-Server)
router.post("/customers", authenticateMerchantAPIKey, customerCreationValidation, CustomerController.createCustomer);

// 2. Info: Can be viewed via either (API or Dashboard)
router.get("/customers/:customerId", authenticateMerchant, CustomerController.getCustomerDetails);
router.get("/customers/:customerId/balance", authenticateMerchant, CustomerController.getCustomerBalance);
router.get("/customers/:customerId/report", authenticateMerchant, CustomerController.getCustomerReport);
router.get("/customers/:customerId/transactions", authenticateMerchant, CustomerController.getCustomerTransactions);
router.post("/customers/:customerId/payout", authenticateMerchant, requireLiveMode, payoutValidation, TransactionController.initiatePayout);
router.post("/customers/:customerId/debit", authenticateMerchant, requireLiveMode, CustomerController.debitCustomer);
router.post("/customers/:customerId/credit", authenticateMerchant, CustomerController.creditCustomer);
router.post("/customers/:customerId/kyc/bvn", authenticateMerchant, bvnKycValidation, CustomerController.verifyCustomerBvn);
router.post("/customers/:customerId/kyc/id", authenticateMerchant, idKycValidation, CustomerController.verifyCustomerId);

// Virtual Card Operations (Merchant)
// NOTE: topup & withdraw are restricted to API Key (server-to-server) only — merchants cannot update card balances from the dashboard.
router.post("/customers/:customerId/cards/register", authenticateMerchant, requireLiveMode, CardController.registerPayscribePerson);
router.post("/customers/:customerId/cards", authenticateMerchant, requireLiveMode, CardController.createCard);
router.get("/customers/:customerId/cards", authenticateMerchant, CustomerController.getCustomerCards || CardController.getCustomerCards);
router.post("/customers/:customerId/cards/:cardId/topup", authenticateMerchantAPIKey, requireLiveMode, CardController.topUpCard);
router.post("/customers/:customerId/cards/:cardId/withdraw", authenticateMerchantAPIKey, requireLiveMode, CardController.withdrawFromCard);
router.post("/customers/:customerId/cards/:cardId/freeze", authenticateMerchant, CardController.freezeCard);
router.post("/customers/:customerId/cards/:cardId/unfreeze", authenticateMerchant, CardController.unfreezeCard);
router.post("/customers/:customerId/cards/:cardId/terminate", authenticateMerchant, CardController.terminateCard);

// Transaction & Bank Tools
router.get("/banks", authenticateMerchant, TransactionController.listBanks);
router.post("/banks/enquiry", authenticateMerchant, TransactionController.resolveAccount);
router.post("/transactions/requery", authenticateMerchant, TransactionController.requeryTransaction);

// Webhooks
router.post("/webhooks/9psb", TransactionController.handleWebhook);
router.post("/webhooks/payscribe", CardController.handlePayscribeWebhook);
router.post("/webhooks/didit", WebhookController.handleDiditWebhook);

export default router;

