import fs from 'fs';
import path from 'path';
import swaggerSpec from '../src/config/swagger.js';
import apiRoutes from '../src/routes/api.js';

const BASE_URL = '{{baseUrl}}';

// Helper to convert route path format: /customers/:customerId -> /customers/{{customerId}} or :customerId -> {{customerId}} for Postman URL
function formatPostmanPath(rawPath) {
  // convert :param to {{param}} or keep path variable format in postman
  const postmanPath = rawPath.replace(/:([a-zA-Z0-9_]+)/g, ':$1');
  return postmanPath;
}

// Convert route parameters for Postman path variables array
function extractUrlVariables(rawPath) {
  const matches = rawPath.match(/:([a-zA-Z0-9_]+)/g);
  if (!matches) return [];
  return matches.map(m => {
    const varName = m.replace(':', '');
    let exampleVal = `{{${varName}}}`;
    if (varName === 'merchantId') exampleVal = '{{merchantId}}';
    else if (varName === 'customerId') exampleVal = '{{customerId}}';
    else if (varName === 'cardId') exampleVal = '{{cardId}}';
    else if (varName === 'serviceId') exampleVal = '{{serviceId}}';
    else if (varName === 'stageId') exampleVal = '{{stageId}}';
    else if (varName === 'id') exampleVal = '{{id}}';
    else if (varName === 'code') exampleVal = 'USD';
    else if (varName === 'slug') exampleVal = 'welcome-email';

    return {
      key: varName,
      value: exampleVal,
      description: `Path variable ${varName}`
    };
  });
}

// Get Swagger doc for route if available
function getSwaggerOperation(routePath, method) {
  const swaggerPaths = swaggerSpec.paths || {};
  // match swagger path style like /admin/merchants/{merchantId}
  const swaggerStylePath = routePath.replace(/:([a-zA-Z0-9_]+)/g, '{$1}');
  const pathItem = swaggerPaths[swaggerStylePath] || swaggerPaths[routePath];
  if (pathItem && pathItem[method.toLowerCase()]) {
    return pathItem[method.toLowerCase()];
  }
  return null;
}

// Build sample JSON body based on path/swagger schema or route defaults
function getSampleBody(path, method, swaggerOp) {
  if (['GET', 'DELETE', 'HEAD'].includes(method)) return null;

  // If swagger requestBody has schema example
  if (swaggerOp && swaggerOp.requestBody && swaggerOp.requestBody.content) {
    const jsonContent = swaggerOp.requestBody.content['application/json'];
    if (jsonContent) {
      if (jsonContent.example) {
        return JSON.stringify(jsonContent.example, null, 2);
      }
      if (jsonContent.examples) {
        const firstEx = Object.values(jsonContent.examples)[0];
        if (firstEx && firstEx.value) {
          return JSON.stringify(firstEx.value, null, 2);
        }
      }
      if (jsonContent.schema) {
        const schema = jsonContent.schema;
        if (schema.example) return JSON.stringify(schema.example, null, 2);
        if (schema.properties) {
          const sample = {};
          Object.keys(schema.properties).forEach(k => {
            const prop = schema.properties[k];
            sample[k] = prop.example !== undefined ? prop.example : (prop.type === 'number' || prop.type === 'integer' ? 100 : (prop.type === 'boolean' ? true : `sample_${k}`));
          });
          return JSON.stringify(sample, null, 2);
        }
      }
    }
  }

  // Fallback default body mapping by route path
  if (path.includes('/admin/login') || path.includes('/merchants/login')) {
    return JSON.stringify({ email: "user@example.com", password: "Password123!" }, null, 2);
  }
  if (path.includes('/verify-otp')) {
    return JSON.stringify({ email: "user@example.com", otp: "123456" }, null, 2);
  }
  if (path.includes('/forgot-password')) {
    return JSON.stringify({ email: "user@example.com" }, null, 2);
  }
  if (path.includes('/reset-password')) {
    return JSON.stringify({ email: "user@example.com", otp: "123456", newPassword: "NewPassword123!" }, null, 2);
  }
  if (path.includes('/2fa/toggle')) {
    return JSON.stringify({ enable: true }, null, 2);
  }
  if (path === '/admin/merchants' && method === 'POST') {
    return JSON.stringify({
      businessName: "Acme Fintech Ltd",
      email: "merchant@acme.com",
      phoneNumber: "+2348012345678",
      password: "MerchantPassword123!"
    }, null, 2);
  }
  if (path.includes('/merchants/register')) {
    return JSON.stringify({
      businessName: "Merchant Enterprise",
      email: "owner@merchant.com",
      phoneNumber: "+2348099998888",
      password: "SecurePassword123!"
    }, null, 2);
  }
  if (path.includes('/customers') && method === 'POST' && path.endsWith('/customers')) {
    return JSON.stringify({
      email: "john.doe@example.com",
      firstName: "John",
      lastName: "Doe",
      phone: "+2348033332222"
    }, null, 2);
  }
  if (path.includes('/payout')) {
    return JSON.stringify({
      amount: 5000,
      accountNumber: "0123456789",
      bankCode: "033",
      accountName: "John Doe",
      narration: "Payout settlement",
      otp: "123456"
    }, null, 2);
  }
  if (path.includes('/cards') && method === 'POST' && path.endsWith('/cards')) {
    return JSON.stringify({
      currency: "USD",
      amount: 20,
      cardType: "virtual"
    }, null, 2);
  }
  if (path.includes('/cards') && (path.endsWith('/topup') || path.endsWith('/withdraw'))) {
    return JSON.stringify({ amount: 50 }, null, 2);
  }
  if (path.includes('/ip-whitelist') && method === 'POST') {
    return JSON.stringify({ ipAddress: "192.168.1.1", label: "Office Network" }, null, 2);
  }
  if (path.includes('/ip-whitelist') && method === 'PATCH') {
    return JSON.stringify({ status: "active", label: "Updated Office IP" }, null, 2);
  }
  if (path.includes('/wallets/swap')) {
    return JSON.stringify({ fromCurrency: "USD", toCurrency: "NGN", amount: 100 }, null, 2);
  }
  if (path.includes('/kyc/bvn')) {
    return JSON.stringify({ bvn: "22233344455", dob: "1990-01-01" }, null, 2);
  }
  if (path.includes('/kyc/id')) {
    return JSON.stringify({ idType: "NIN", idNumber: "12345678901" }, null, 2);
  }
  if (path.includes('/banks/enquiry')) {
    return JSON.stringify({ accountNumber: "0123456789", bankCode: "033" }, null, 2);
  }
  if (path.includes('/transactions/requery')) {
    return JSON.stringify({ transactionReference: "TXN_123456789" }, null, 2);
  }
  if (path.includes('/webhooks/')) {
    return JSON.stringify({ event: "transaction.success", data: { reference: "REF123", amount: 1000 } }, null, 2);
  }

  return JSON.stringify({ status: "active" }, null, 2);
}

// Determine auth type for folder/request
function getAuthForRoute(path) {
  if (path.startsWith('/admin')) {
    if (path.includes('/admin/login') || path.includes('/admin/verify-otp') || path.includes('/admin/forgot-password') || path.includes('/admin/reset-password')) {
      return { type: 'noauth' };
    }
    return {
      type: 'bearer',
      bearer: [{ key: 'token', value: '{{adminToken}}', type: 'string' }]
    };
  }

  if (path.startsWith('/customers')) {
    if (path === '/customers' || path.includes('/cards/topup') || path.includes('/cards/withdraw')) {
      return {
        type: 'apikey',
        apikey: [
          { key: 'key', value: 'x-public-key', type: 'string' },
          { key: 'value', value: '{{apiKey}}', type: 'string' },
          { key: 'in', value: 'header', type: 'string' }
        ]
      };
    }
    return {
      type: 'bearer',
      bearer: [{ key: 'token', value: '{{merchantToken}}', type: 'string' }]
    };
  }

  if (path.startsWith('/merchants')) {
    if (path.includes('/merchants/register') || path.includes('/merchants/login') || path.includes('/merchants/verify-otp') || path.includes('/merchants/forgot-password') || path.includes('/merchants/reset-password')) {
      return { type: 'noauth' };
    }
    return {
      type: 'bearer',
      bearer: [{ key: 'token', value: '{{merchantToken}}', type: 'string' }]
    };
  }

  if (path.startsWith('/webhooks')) {
    return { type: 'noauth' };
  }

  return { type: 'noauth' };
}

// Determine extra headers required
function getHeadersForRoute(path) {
  const headers = [
    { key: 'Content-Type', value: 'application/json' }
  ];

  if (path === '/customers' || path.includes('/cards/topup') || path.includes('/cards/withdraw')) {
    headers.push({ key: 'x-public-key', value: '{{apiKey}}', description: 'Merchant Public Key' });
    headers.push({ key: 'x-private-key', value: '{{secretKey}}', description: 'Merchant Private Key' });
  }

  if (path.includes('/merchants/payout') || path.includes('/merchants/pricing') || path.includes('/merchants/rates') || path.includes('/merchants/wallets')) {
    headers.push({ key: 'x-public-key', value: '{{apiKey}}', description: 'Optional API Public Key for S2S' });
    headers.push({ key: 'x-private-key', value: '{{secretKey}}', description: 'Optional API Private Key for S2S' });
  }

  return headers;
}

// Map endpoints to Folders
const FOLDER_DEFINITIONS = [
  {
    name: "01. System & Operational Health",
    description: "System health check and root operational endpoints",
    match: (p) => p === "/" || p === "/api/v1"
  },
  {
    name: "02. Admin - Auth & Security",
    description: "SuperAdmin and Admin login, OTP verification, password reset, and 2FA management",
    match: (p) => p.startsWith("/admin") && (p.includes("login") || p.includes("verify-otp") || p.includes("forgot-password") || p.includes("reset-password") || p.includes("2fa"))
  },
  {
    name: "03. Admin - Merchant Management",
    description: "SuperAdmin onboarding of merchants, merchant status management, fee structures, and merchant stats",
    match: (p) => p.startsWith("/admin/merchants") && !p.includes("/cards")
  },
  {
    name: "04. Admin - Dashboard & Analytics",
    description: "Platform-wide dashboard statistics, financial report generation, system profit analytics, transactions, and customer management",
    match: (p) => p.startsWith("/admin") && (p.includes("dashboard") || p.includes("report") || p.includes("profits") || p.includes("transactions") || p.includes("customers")) && !p.includes("/cards")
  },
  {
    name: "05. Admin - IP Whitelist Management",
    description: "SuperAdmin control for IP whitelisting across administrative users",
    match: (p) => p.startsWith("/admin/ip-whitelist")
  },
  {
    name: "06. Admin - Card Management",
    description: "SuperAdmin and Admin virtual card controls: freeze, unfreeze, terminate, balance updates, and card lookup",
    match: (p) => p.startsWith("/admin") && p.includes("/cards")
  },
  {
    name: "07. Admin - KYB Review",
    description: "SuperAdmin review and status updates for Merchant Know Your Business (KYB) applications",
    match: (p) => p.startsWith("/admin/kyb")
  },
  {
    name: "08. Admin - Settings & Services & KYC Stages",
    description: "Global system settings, dynamic fee config, system service toggles, and KYC stage mappings",
    match: (p) => p.startsWith("/admin") && (p.includes("settings") || p.includes("services") || p.includes("kyc/stages"))
  },
  {
    name: "09. Admin - Currency Management",
    description: "Global multi-currency configuration and virtual account capabilities",
    match: (p) => p.startsWith("/admin/currencies")
  },
  {
    name: "10. Admin - Service Pricing",
    description: "Service pricing tiers and tier rates configuration",
    match: (p) => p.startsWith("/admin/service-pricing")
  },
  {
    name: "11. Admin - Email Templates",
    description: "Email template management for automated system notifications",
    match: (p) => p.startsWith("/admin/email-templates")
  },
  {
    name: "12. Admin - Exchange Rates",
    description: "Foreign exchange rate definitions, live rate previews, and FX markup controls",
    match: (p) => p.startsWith("/admin/exchange-rates")
  },
  {
    name: "13. Admin - Subscription Plans",
    description: "SaaS subscription tier management and global subscription metrics",
    match: (p) => p.startsWith("/admin/subscription-plans") || p.startsWith("/admin/subscriptions")
  },
  {
    name: "14. Merchant - Auth & Key Management",
    description: "Merchant self-registration, dashboard auth, API key generation, webhook URL setup, and profile settings",
    match: (p) => p.startsWith("/merchants") && (p.includes("register") || p.includes("login") || p.includes("verify-otp") || p.includes("forgot-password") || p.includes("reset-password") || p.includes("2fa") || p.includes("keys") || p === "/merchants/webhook" || p.includes("profile") || p.includes("payout/request-otp"))
  },
  {
    name: "15. Merchant - KYB Application",
    description: "Merchant business verification form submission and status checks",
    match: (p) => p.startsWith("/merchants/kyb")
  },
  {
    name: "16. Merchant - Subscriptions",
    description: "Merchant SaaS subscription plan lookup, subscription upgrade/downgrade, invoices, and billing history",
    match: (p) => p.startsWith("/merchants/subscriptions")
  },
  {
    name: "17. Merchant - Dashboard & Wallets & Payouts",
    description: "Merchant balance check, multi-currency wallets, currency swap, payout execution, pricing, exchange rates, and IP whitelisting",
    match: (p) => p.startsWith("/merchants") && !p.startsWith("/merchants/webhooks") && (p.includes("me") || p.includes("stats") || p.includes("transactions") || p.includes("customers") || p.includes("ip-whitelist") || p.includes("payout") || p.includes("pricing") || p.includes("rates") || p.includes("wallets"))
  },
  {
    name: "18. Merchant - Webhook Logs",
    description: "Merchant dashboard incoming and outgoing webhook delivery logs and manual retry/resend options",
    match: (p) => p.startsWith("/merchants/webhooks")
  },
  {
    name: "19. Customer Management & KYC",
    description: "Customer creation via Server-to-Server API Keys, balance queries, financial reports, customer payouts, debits/credits, BVN verification, and ID verification",
    match: (p) => p.startsWith("/customers") && !p.includes("/cards")
  },
  {
    name: "20. Customer Virtual Cards",
    description: "Customer card creation, Payscribe identity registration, card listing, top-up, withdrawal, freeze, unfreeze, and termination",
    match: (p) => p.startsWith("/customers") && p.includes("/cards")
  },
  {
    name: "21. Banks & Transaction Requery",
    description: "Supported bank listing, account resolution/name enquiry, and transaction status requery tools",
    match: (p) => p.startsWith("/banks") || p.startsWith("/transactions")
  },
  {
    name: "22. Inbound Provider Webhooks",
    description: "Callback webhooks for payment gateway (9PSB), card provider (Payscribe), and identity verifier (Didit)",
    match: (p) => p.startsWith("/webhooks")
  }
];

// Extract Express routes
const allRoutes = [];

// Root app route
allRoutes.push({
  path: '/',
  method: 'GET',
  description: 'Check SaaS Operational Status'
});

apiRoutes.stack.forEach((middleware) => {
  if (middleware.route) {
    const rawPath = middleware.route.path;
    const fullPath = '/api/v1' + rawPath;
    const methods = Object.keys(middleware.route.methods).map(m => m.toUpperCase());

    methods.forEach(method => {
      allRoutes.push({
        rawPath: rawPath,
        fullPath: fullPath,
        method: method
      });
    });
  }
});

console.log(`Total routes collected for Postman: ${allRoutes.length}`);

// Group routes into folders
const folderItemsMap = {};
FOLDER_DEFINITIONS.forEach(f => {
  folderItemsMap[f.name] = {
    name: f.name,
    description: f.description,
    item: []
  };
});

allRoutes.forEach(r => {
  const routePath = r.rawPath || r.path;
  const swaggerOp = getSwaggerOperation(routePath, r.method);

  let summary = swaggerOp ? (swaggerOp.summary || swaggerOp.description) : null;
  if (!summary) {
    summary = `${r.method} ${r.fullPath || r.path}`;
  }

  let folderDef = FOLDER_DEFINITIONS.find(f => f.match(routePath));
  if (!folderDef) {
    console.warn(`Warning: No matching folder for ${r.method} ${routePath}, placing in System folder`);
    folderDef = FOLDER_DEFINITIONS[0];
  }

  const postmanPath = r.fullPath ? r.fullPath : r.path;
  const pathSegments = postmanPath.split('/').filter(Boolean);
  const urlVariables = extractUrlVariables(routePath);
  const auth = getAuthForRoute(routePath);
  const headers = getHeadersForRoute(routePath);
  const sampleBody = getSampleBody(routePath, r.method, swaggerOp);

  const requestItem = {
    name: summary,
    request: {
      auth: auth.type !== 'noauth' ? auth : undefined,
      method: r.method,
      header: headers,
      url: {
        raw: `${BASE_URL}${postmanPath}`,
        host: [BASE_URL],
        path: pathSegments,
        variable: urlVariables.length > 0 ? urlVariables : undefined
      },
      description: swaggerOp ? (swaggerOp.description || summary) : summary
    },
    response: []
  };

  if (sampleBody && !['GET', 'DELETE', 'HEAD'].includes(r.method)) {
    requestItem.request.body = {
      mode: 'raw',
      raw: sampleBody,
      options: {
        raw: {
          language: 'json'
        }
      }
    };
  }

  folderItemsMap[folderDef.name].item.push(requestItem);
});

// Construct Postman Collection Structure
const postmanCollection = {
  info: {
    _postman_id: "airpero-saas-api-v1-collection",
    name: "Airpero SaaS Backend API Collection",
    description: "Complete Postman API Collection for Airpero SaaS Backend (Multi-tenant SaaS for 9PSB Naira integration, Virtual Cards, Merchant Dashboards, and SuperAdmin controls).\n\nIncludes all 125 system endpoints across Admin, Merchant, Customer, and Provider Webhook domains.",
    schema: "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  item: FOLDER_DEFINITIONS.map(f => folderItemsMap[f.name]),
  variable: [
    {
      key: "baseUrl",
      value: "http://localhost:8200",
      type: "string",
      description: "Base API host URL"
    },
    {
      key: "adminToken",
      value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      type: "string",
      description: "JWT Token for Admin / SuperAdmin requests"
    },
    {
      key: "merchantToken",
      value: "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
      type: "string",
      description: "JWT Token for Merchant Dashboard requests"
    },
    {
      key: "apiKey",
      value: "pk_live_airpero_sample_public_key",
      type: "string",
      description: "Merchant Public Key for S2S API authentication (x-public-key)"
    },
    {
      key: "secretKey",
      value: "sk_live_airpero_sample_private_key",
      type: "string",
      description: "Merchant Private Key for S2S API authentication (x-private-key)"
    },
    {
      key: "merchantId",
      value: "1",
      type: "string",
      description: "Sample Merchant ID parameter"
    },
    {
      key: "customerId",
      value: "1",
      type: "string",
      description: "Sample Customer ID parameter"
    },
    {
      key: "cardId",
      value: "1",
      type: "string",
      description: "Sample Card ID parameter"
    },
    {
      key: "serviceId",
      value: "1",
      type: "string",
      description: "Sample Service ID parameter"
    },
    {
      key: "stageId",
      value: "1",
      type: "string",
      description: "Sample KYC Stage ID parameter"
    },
    {
      key: "id",
      value: "1",
      type: "string",
      description: "Generic entity ID parameter"
    }
  ]
};

// Write Postman Collection JSON to project root
const outputPath = path.join(process.cwd(), 'Airpero_SaaS_API.postman_collection.json');
fs.writeFileSync(outputPath, JSON.stringify(postmanCollection, null, 2), 'utf8');
console.log(`✅ Successfully generated Postman collection at: ${outputPath}`);

// Also copy to artifacts directory if available
const artifactDir = 'C:\\Users\\OWNER\\.gemini\\antigravity-cli\\brain\\4fdb46f1-d208-4477-a107-977bf0b5c041';
if (fs.existsSync(artifactDir)) {
  const artifactPath = path.join(artifactDir, 'Airpero_SaaS_API.postman_collection.json');
  fs.writeFileSync(artifactPath, JSON.stringify(postmanCollection, null, 2), 'utf8');
  console.log(`✅ Successfully copied Postman collection to artifact path: ${artifactPath}`);
}
