import { Request, Response } from 'express';
import prisma from '../../../config/database';
import { sendSuccess, sendError } from '../../../utils/response.utils';
import { AuthenticatedRequest } from '../../../middleware/auth.middleware';
import { encrypt, decrypt, maskSecret } from '../../../utils/encryption.utils';
import { logger } from '../../../config/logger';

// 1. Public Gateway Settings List (enabled checkout payment systems only, no secrets exposed)
export const getPublicGateways = async (_req: Request, res: Response) => {
  try {
    const settings = await prisma.paymentGatewaySetting.findMany({
      where: { isEnabled: true },
      orderBy: { sortOrder: 'asc' },
      select: {
        id: true,
        gatewayName: true,
        displayName: true,
        environment: true,
        currency: true,
        minAmount: true,
        maxAmount: true,
        processingFee: true,
        sortOrder: true,
      },
    });

    return sendSuccess(res, 'Active checkout payment options retrieved', { gateways: settings });
  } catch (error: any) {
    return sendError(res, 'Failed to retrieve payment gateways', error.message, 500);
  }
};

// 2. Admin Gateways Settings List (Masked credentials)
export const getAdminGateways = async (req: AuthenticatedRequest, res: Response) => {
  try {
    // Only ADMIN role authorized
    if (res.locals.userRole !== 'ADMIN' && req.user?.role !== 'ADMIN') {
      return sendError(res, 'Unauthorized to view credentials settings', null, 403);
    }

    const settings = await prisma.paymentGatewaySetting.findMany({
      orderBy: { sortOrder: 'asc' },
    });

    // Mask sensitive configurations for security audit
    const maskedSettings = settings.map((s) => ({
      ...s,
      keySecret: s.keySecret ? maskSecret(s.keySecret) : null,
      clientSecret: s.clientSecret ? maskSecret(s.clientSecret) : null,
      saltKey: s.saltKey ? maskSecret(s.saltKey) : null,
      webhookSecret: s.webhookSecret ? maskSecret(s.webhookSecret) : null,
    }));

    return sendSuccess(res, 'Admin payment configurations retrieved', { gateways: maskedSettings });
  } catch (error: any) {
    return sendError(res, 'Admin retrieval failed', error.message, 500);
  }
};

// 3. Create Gateway configuration
export const createGatewayConfig = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const {
      gatewayName,
      displayName,
      isEnabled,
      environment,
      merchantId,
      clientId,
      clientSecret,
      keyId,
      keySecret,
      saltKey,
      saltIndex,
      webhookSecret,
      callbackUrl,
      webhookUrl,
      currency,
      minAmount,
      maxAmount,
      processingFee,
      sortOrder,
    } = req.body;

    const gateway = await prisma.paymentGatewaySetting.create({
      data: {
        gatewayName: gatewayName.toUpperCase(),
        displayName,
        isEnabled: isEnabled ?? true,
        environment: environment || 'sandbox',
        merchantId,
        clientId,
        clientSecret: clientSecret ? encrypt(clientSecret) : null,
        keyId,
        keySecret: keySecret ? encrypt(keySecret) : null,
        saltKey: saltKey ? encrypt(saltKey) : null,
        saltIndex,
        webhookSecret: webhookSecret ? encrypt(webhookSecret) : null,
        callbackUrl,
        webhookUrl,
        currency: currency || 'INR',
        minAmount: minAmount ?? 1.0,
        maxAmount: maxAmount ?? 500000.0,
        processingFee: processingFee ?? 0.0,
        sortOrder: sortOrder ?? 0,
      },
    });

    return sendSuccess(res, 'Gateway configuration created successfully', { id: gateway.id });
  } catch (error: any) {
    return sendError(res, 'Failed to create configuration', error.message, 500);
  }
};

// 4. Update Gateway credentials configuration (Encrypting sensitive fields)
export const updateGatewayConfig = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    const body = req.body;

    const existing = await prisma.paymentGatewaySetting.findUnique({ where: { id } });
    if (!existing) return sendError(res, 'Gateway configuration not found', null, 404);

    // Keep decrypted secret if it is still masked (************) in the update request
    const clientSecret = body.clientSecret === '************' ? existing.clientSecret : (body.clientSecret ? encrypt(body.clientSecret) : null);
    const keySecret = body.keySecret === '************' ? existing.keySecret : (body.keySecret ? encrypt(body.keySecret) : null);
    const saltKey = body.saltKey === '************' ? existing.saltKey : (body.saltKey ? encrypt(body.saltKey) : null);
    const webhookSecret = body.webhookSecret === '************' ? existing.webhookSecret : (body.webhookSecret ? encrypt(body.webhookSecret) : null);

    await prisma.paymentGatewaySetting.update({
      where: { id },
      data: {
        displayName: body.displayName,
        isEnabled: body.isEnabled,
        environment: body.environment,
        merchantId: body.merchantId,
        clientId: body.clientId,
        clientSecret,
        keyId: body.keyId,
        keySecret,
        saltKey,
        saltIndex: body.saltIndex,
        webhookSecret,
        callbackUrl: body.callbackUrl,
        webhookUrl: body.webhookUrl,
        currency: body.currency,
        minAmount: body.minAmount,
        maxAmount: body.maxAmount,
        processingFee: body.processingFee,
        sortOrder: body.sortOrder,
      },
    });

    // Write audit log
    await prisma.activityLog.create({
      data: {
        adminId: req.user?.adminId,
        action: 'PAYMENT_GATEWAY_CONFIG_UPDATED',
        details: { gatewayName: existing.gatewayName },
      },
    });

    logger.info(`Payment Gateway configuration updated for: ${existing.gatewayName}`);
    return sendSuccess(res, 'Gateway configuration updated successfully');
  } catch (error: any) {
    return sendError(res, 'Update failed', error.message, 500);
  }
};

// 5. Toggle enable / disable status
export const toggleGateway = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    const existing = await prisma.paymentGatewaySetting.findUnique({ where: { id } });
    if (!existing) return sendError(res, 'Gateway not found', null, 404);

    const updated = await prisma.paymentGatewaySetting.update({
      where: { id },
      data: { isEnabled: !existing.isEnabled },
    });

    return sendSuccess(res, `Gateway status toggled to: ${updated.isEnabled ? 'Enabled' : 'Disabled'}`, { isEnabled: updated.isEnabled });
  } catch (error: any) {
    return sendError(res, 'Toggle failed', error.message, 500);
  }
};

// 6. Delete config
export const deleteGateway = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    await prisma.paymentGatewaySetting.delete({ where: { id } });
    return sendSuccess(res, 'Gateway configuration deleted successfully');
  } catch (error: any) {
    return sendError(res, 'Deletion failed', error.message, 500);
  }
};

// 7. Connection status check / Test connection api
export const testGatewayConnection = async (req: AuthenticatedRequest, res: Response) => {
  try {
    const { id } = req.params;
    const gateway = await prisma.paymentGatewaySetting.findUnique({ where: { id } });
    if (!gateway) return sendError(res, 'Gateway configuration not found', null, 404);

    // Mock API connection request depending on gateway keys.
    // If key ID starts with "invalid" or keys are empty, connection fails.
    const isSuccess = gateway.keyId !== 'invalid' && (gateway.isEnabled || gateway.displayName !== '');

    logger.info(`Tested gateway connection for ${gateway.gatewayName}: ${isSuccess ? 'CONNECTED' : 'FAILED'}`);

    return sendSuccess(res, 'Tested connection parameters', {
      connected: isSuccess,
      status: isSuccess ? 'Connected' : 'Failed',
    });
  } catch (error: any) {
    return sendError(res, 'Connection test failed', error.message, 500);
  }
};
