// src/utils/apiResponse.ts
// ============================================================================
// API RESPONSE HELPERS
// ============================================================================
// Utility functions for creating standardized API responses per ADR-028.
// Use these helpers in all route handlers for consistent response formats.
// ============================================================================

import { Response } from 'express';
import {
  ApiSuccessResponse,
  ApiErrorResponse,
  PaginationInput,
  PaginationMeta,
  ResponseMeta,
  ErrorCodeType,
  ErrorCode,
} from '../types/api';

/**
 * Send a successful response with data.
 *
 * @param res - Express response object
 * @param data - The response data
 * @param statusCode - HTTP status code (default: 200)
 * @param meta - Optional metadata (requestId, timestamp)
 *
 * @example
 * // Simple success response
 * sendSuccess(res, { id: 1, name: 'Item' });
 *
 * @example
 * // Success with 201 Created
 * sendSuccess(res, newUser, 201);
 */
export function sendSuccess<T>(
  res: Response,
  data: T,
  statusCode: number = 200,
  meta?: Omit<ResponseMeta, 'pagination'>,
): Response<ApiSuccessResponse<T>> {
  const response: ApiSuccessResponse<T> = {
    success: true,
    data,
  };

  if (meta) {
    response.meta = meta;
  }

  return res.status(statusCode).json(response);
}

/**
 * Send a successful response with no content (204).
 * Used for DELETE operations or actions that don't return data.
 *
 * @param res - Express response object
 *
 * @example
 * // After deleting a resource
 * sendNoContent(res);
 */
export function sendNoContent(res: Response): Response {
  return res.status(204).send();
}

/**
 * Calculate pagination metadata from input parameters.
 *
 * @param input - Pagination input (page, limit, total)
 * @returns Calculated pagination metadata
 */
export function calculatePagination(input: PaginationInput): PaginationMeta {
  const { page, limit, total } = input;
  const totalPages = Math.ceil(total / limit);

  return {
    page,
    limit,
    total,
    totalPages,
    hasNextPage: page < totalPages,
    hasPrevPage: page > 1,
  };
}

/**
 * Send a paginated success response.
 *
 * @param res - Express response object
 * @param data - The array of items for the current page
 * @param pagination - Pagination input (page, limit, total)
 * @param meta - Optional additional metadata
 *
 * @example
 * const { flyers, total } = await flyerService.getFlyers({ page, limit });
 * sendPaginated(res, flyers, { page, limit, total });
 */
export function sendPaginated<T>(
  res: Response,
  data: T[],
  pagination: PaginationInput,
  meta?: Omit<ResponseMeta, 'pagination'>,
): Response<ApiSuccessResponse<T[]>> {
  const response: ApiSuccessResponse<T[]> = {
    success: true,
    data,
    meta: {
      ...meta,
      pagination: calculatePagination(pagination),
    },
  };

  return res.status(200).json(response);
}

/**
 * Send an error response.
 *
 * @param res - Express response object
 * @param code - Machine-readable error code
 * @param message - Human-readable error message
 * @param statusCode - HTTP status code (default: 400)
 * @param details - Optional error details (validation errors, etc.)
 * @param meta - Optional metadata (requestId for error tracking)
 *
 * @example
 * // Validation error
 * sendError(res, ErrorCode.VALIDATION_ERROR, 'Invalid email format', 400, errors);
 *
 * @example
 * // Not found error
 * sendError(res, ErrorCode.NOT_FOUND, 'User not found', 404);
 */
export function sendError(
  res: Response,
  code: ErrorCodeType | string,
  message: string,
  statusCode: number = 400,
  details?: unknown,
  meta?: Pick<ResponseMeta, 'requestId' | 'timestamp'>,
): Response<ApiErrorResponse> {
  const response: ApiErrorResponse = {
    success: false,
    error: {
      code,
      message,
    },
  };

  if (details !== undefined) {
    response.error.details = details;
  }

  if (meta) {
    response.meta = meta;
  }

  return res.status(statusCode).json(response);
}

/**
 * Send a message-only success response.
 * Useful for operations that complete successfully but don't return data.
 *
 * @param res - Express response object
 * @param message - Success message
 * @param statusCode - HTTP status code (default: 200)
 *
 * @example
 * sendMessage(res, 'Password updated successfully');
 */
export function sendMessage(
  res: Response,
  message: string,
  statusCode: number = 200,
): Response<ApiSuccessResponse<{ message: string }>> {
  return sendSuccess(res, { message }, statusCode);
}

// Re-export ErrorCode for convenience
export { ErrorCode };
