/**
 * API Types - Core Module
 *
 * Tipos compartidos para APIs REST en todos los proyectos.
 *
 * @module @core/types/api
 * @version 1.0.0
 */

import { SortDirection } from '../constants/enums.constants';

// ============================================================================
// API RESPONSE TYPES
// ============================================================================

/**
 * Standard API response wrapper
 */
export interface ApiResponse<T = unknown> {
  success: boolean;
  data: T;
  message?: string;
  timestamp: string;
  path?: string;
  requestId?: string;
}

/**
 * API error response
 */
export interface ApiError {
  success: false;
  error: {
    code: string;
    message: string;
    details?: Record<string, unknown>;
    stack?: string; // Only in development
  };
  timestamp: string;
  path?: string;
  requestId?: string;
}

/**
 * Paginated response
 */
export interface PaginatedResponse<T> extends ApiResponse<T[]> {
  pagination: PaginationMeta;
}

/**
 * Pagination metadata
 */
export interface PaginationMeta {
  page: number;
  limit: number;
  total: number;
  totalPages: number;
  hasNext: boolean;
  hasPrev: boolean;
}

// ============================================================================
// REQUEST TYPES
// ============================================================================

/**
 * Pagination query parameters
 */
export interface PaginationParams {
  page?: number;
  limit?: number;
}

/**
 * Sort query parameters
 */
export interface SortParams {
  sortBy?: string;
  sortOrder?: SortDirection;
}

/**
 * Combined query parameters
 */
export interface QueryParams extends PaginationParams, SortParams {
  search?: string;
  filter?: Record<string, unknown>;
}

/**
 * Date range filter
 */
export interface DateRangeFilter {
  startDate?: string;
  endDate?: string;
}

// ============================================================================
// CRUD OPERATIONS
// ============================================================================

/**
 * Create operation result
 */
export interface CreateResult<T> {
  created: T;
  message?: string;
}

/**
 * Update operation result
 */
export interface UpdateResult<T> {
  updated: T;
  message?: string;
}

/**
 * Delete operation result
 */
export interface DeleteResult {
  deleted: boolean;
  id: string;
  message?: string;
}

/**
 * Bulk operation result
 */
export interface BulkResult {
  success: number;
  failed: number;
  errors?: Array<{
    id: string;
    error: string;
  }>;
}

// ============================================================================
// HEALTH CHECK
// ============================================================================

/**
 * Health check response
 */
export interface HealthCheckResponse {
  status: 'healthy' | 'degraded' | 'unhealthy';
  timestamp: string;
  version: string;
  uptime: number;
  services?: Record<string, ServiceHealth>;
}

/**
 * Individual service health
 */
export interface ServiceHealth {
  status: 'up' | 'down' | 'degraded';
  latency?: number;
  message?: string;
}

// ============================================================================
// ERROR CODES
// ============================================================================

/**
 * Standard error codes
 */
export const ErrorCodes = {
  // Client errors (4xx)
  BAD_REQUEST: 'BAD_REQUEST',
  UNAUTHORIZED: 'UNAUTHORIZED',
  FORBIDDEN: 'FORBIDDEN',
  NOT_FOUND: 'NOT_FOUND',
  METHOD_NOT_ALLOWED: 'METHOD_NOT_ALLOWED',
  CONFLICT: 'CONFLICT',
  UNPROCESSABLE_ENTITY: 'UNPROCESSABLE_ENTITY',
  TOO_MANY_REQUESTS: 'TOO_MANY_REQUESTS',

  // Server errors (5xx)
  INTERNAL_ERROR: 'INTERNAL_ERROR',
  SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE',
  GATEWAY_TIMEOUT: 'GATEWAY_TIMEOUT',

  // Validation errors
  VALIDATION_ERROR: 'VALIDATION_ERROR',
  INVALID_INPUT: 'INVALID_INPUT',
  MISSING_FIELD: 'MISSING_FIELD',

  // Auth errors
  INVALID_CREDENTIALS: 'INVALID_CREDENTIALS',
  TOKEN_EXPIRED: 'TOKEN_EXPIRED',
  TOKEN_INVALID: 'TOKEN_INVALID',
  SESSION_EXPIRED: 'SESSION_EXPIRED',

  // Business logic errors
  RESOURCE_EXISTS: 'RESOURCE_EXISTS',
  RESOURCE_LOCKED: 'RESOURCE_LOCKED',
  OPERATION_FAILED: 'OPERATION_FAILED',
  LIMIT_EXCEEDED: 'LIMIT_EXCEEDED',
} as const;

export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes];

// ============================================================================
// HTTP STATUS
// ============================================================================

/**
 * HTTP status codes mapping
 */
export const HttpStatus = {
  OK: 200,
  CREATED: 201,
  ACCEPTED: 202,
  NO_CONTENT: 204,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  METHOD_NOT_ALLOWED: 405,
  CONFLICT: 409,
  UNPROCESSABLE_ENTITY: 422,
  TOO_MANY_REQUESTS: 429,
  INTERNAL_SERVER_ERROR: 500,
  BAD_GATEWAY: 502,
  SERVICE_UNAVAILABLE: 503,
  GATEWAY_TIMEOUT: 504,
} as const;

export type HttpStatusCode = (typeof HttpStatus)[keyof typeof HttpStatus];

// ============================================================================
// HELPER FUNCTIONS
// ============================================================================

/**
 * Create success response
 */
export const createSuccessResponse = <T>(
  data: T,
  message?: string,
): ApiResponse<T> => ({
  success: true,
  data,
  message,
  timestamp: new Date().toISOString(),
});

/**
 * Create error response
 */
export const createErrorResponse = (
  code: ErrorCode,
  message: string,
  details?: Record<string, unknown>,
): ApiError => ({
  success: false,
  error: {
    code,
    message,
    details,
  },
  timestamp: new Date().toISOString(),
});

/**
 * Create paginated response
 */
export const createPaginatedResponse = <T>(
  data: T[],
  page: number,
  limit: number,
  total: number,
): PaginatedResponse<T> => {
  const totalPages = Math.ceil(total / limit);
  return {
    success: true,
    data,
    timestamp: new Date().toISOString(),
    pagination: {
      page,
      limit,
      total,
      totalPages,
      hasNext: page < totalPages,
      hasPrev: page > 1,
    },
  };
};

/**
 * Calculate pagination offset
 */
export const calculateOffset = (page: number, limit: number): number => {
  return (page - 1) * limit;
};

/**
 * Normalize pagination params
 */
export const normalizePagination = (
  params: PaginationParams,
  defaults: { page: number; limit: number; maxLimit: number } = {
    page: 1,
    limit: 20,
    maxLimit: 100,
  },
): Required<PaginationParams> => ({
  page: Math.max(1, params.page || defaults.page),
  limit: Math.min(
    defaults.maxLimit,
    Math.max(1, params.limit || defaults.limit),
  ),
});
