/**
 * HANA Query API Client - Configuration
 * 
 * Default configuration and environment-specific settings for the API client.
 */

import type { ClientConfig } from './types.ts';

/**
 * Default client configuration (excluding baseUrl which is required)
 */
export const DEFAULT_CONFIG = {
  timeout: 30000,          // 30 seconds
  retries: 3,
  retryDelay: 1000,        // 1 second base delay
  enableLogging: false,
  logLevel: 'info' as const,
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json'
  }
};

/**
 * Environment-specific configurations
 */
export const ENVIRONMENT_CONFIGS: Record<string, ClientConfig> = {
  development: {
    baseUrl: 'http://localhost:3001',
    enableLogging: true,
    logLevel: 'debug',
    timeout: 10000
  },
  
  testing: {
    baseUrl: 'http://localhost:3001',
    enableLogging: true,
    logLevel: 'warn',
    timeout: 5000,
    retries: 1
  },
  
  staging: {
    baseUrl: 'https://api-staging.example.com',
    enableLogging: true,
    logLevel: 'info',
    timeout: 20000
  },
  
  production: {
    baseUrl: 'https://api.example.com',
    enableLogging: false,
    logLevel: 'error',
    timeout: 30000
  }
};

/**
 * API version and paths
 */
export const API_VERSION = 'v1';
export const API_BASE_PATH = `/api/${API_VERSION}`;

/**
 * Endpoint paths
 */
export const ENDPOINTS = {
  HEALTH: '/health',
  DOCS: '/docs',
  ITEMS: '/items',
  ITEMS_GROUPS: '/items/groups',
  ITEMS_HIERARCHIES: '/items/hierarchies',
  ITEMS_TREES: '/items/trees',
  ITEMS_QTY_PER_TAG: '/items/qty-per-tag',
  SALES: '/sales',
  PRODUCTION_SECTORS: '/production-sectors',
  DATABASE_COMPANIES: '/database-companies',
  PLANS: '/plans',
  ALL_PLANS_SECTORS: '/plans/sectors',
  PLAN_DETAIL: '/plans/{planId}',
  PLAN_PRODUCTS: '/plans/{planId}/products',
  PLAN_WORK_ORDERS: '/plans/{planId}/work-orders',
  PLAN_SECTORS: '/plans/{planId}/sectors',
  PLAN_TAGS: '/plans/{planId}/tags',
  USER: '/users/{username}',
  TAG: '/tags/{tagEntry}',
  WORK_ORDER_TAGS: '/work-orders/{workOrderEntry}/tags',
  INJECTION_MACHINES: '/injection-machines',
  INJECTION_MACHINE: '/injection-machines/{machineCode}',
  MOLDS: '/molds',
  MOLD: '/molds/{moldCode}',
  BUSINESS_PARTNERS: '/business-partners',
  BUSINESS_PARTNERS_SEARCH: '/business-partners/search',
  BUSINESS_PARTNER_CONTACTS: '/business-partners/{cardCode}/contacts',
  CONTACTS: '/contacts',
  CONTACTS_SEARCH: '/contacts/search'
} as const;

/**
 * HTTP status codes
 */
export const HTTP_STATUS = {
  OK: 200,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  INTERNAL_SERVER_ERROR: 500,
  BAD_GATEWAY: 502,
  SERVICE_UNAVAILABLE: 503,
  GATEWAY_TIMEOUT: 504
} as const;

/**
 * Request timeout configuration for different endpoint types
 */
export const ENDPOINT_TIMEOUTS = {
  // Fast endpoints
  [ENDPOINTS.HEALTH]: 5000,
  [ENDPOINTS.DOCS]: 5000,
  [ENDPOINTS.PLANS]: 15000,
  [ENDPOINTS.ALL_PLANS_SECTORS]: 30000,
  [ENDPOINTS.PLAN_DETAIL]: 10000,
  [ENDPOINTS.PLAN_PRODUCTS]: 10000,
  [ENDPOINTS.PLAN_WORK_ORDERS]: 10000,
  [ENDPOINTS.PLAN_SECTORS]: 15000,
  [ENDPOINTS.PLAN_TAGS]: 10000,
  [ENDPOINTS.USER]: 10000,
  [ENDPOINTS.DATABASE_COMPANIES]: 5000,  // Fast lookup endpoint
  [ENDPOINTS.PRODUCTION_SECTORS]: 5000,
  [ENDPOINTS.TAG]: 10000,                  // Single tag lookup
  [ENDPOINTS.WORK_ORDER_TAGS]: 15000,      // All tags for a work order
  [ENDPOINTS.INJECTION_MACHINES]: 10000,   // All injection machines
  [ENDPOINTS.INJECTION_MACHINE]: 10000,    // Single injection machine
  [ENDPOINTS.MOLDS]: 10000,                // All molds
  [ENDPOINTS.MOLD]: 10000,                 // Single mold
  
  // Slower endpoints with large datasets
  [ENDPOINTS.ITEMS]: 60000,                // Items can be large
  [ENDPOINTS.SALES]: 60000,                // Sales can be large with date ranges
  [ENDPOINTS.ITEMS_HIERARCHIES]: 90000,    // Hierarchies are the largest
  [ENDPOINTS.ITEMS_TREES]: 90000,          // Trees can also be large
  [ENDPOINTS.ITEMS_QTY_PER_TAG]: 30000,    // Qty per tag data

  // Business partners / contacts — full table scans, no fulltext indexes yet
  [ENDPOINTS.BUSINESS_PARTNERS]: 60000,
  [ENDPOINTS.BUSINESS_PARTNERS_SEARCH]: 90000,
  [ENDPOINTS.BUSINESS_PARTNER_CONTACTS]: 15000,
  [ENDPOINTS.CONTACTS]: 60000,
  [ENDPOINTS.CONTACTS_SEARCH]: 90000
} as const;

/**
 * Retry configuration for different error types
 */
export const RETRY_CONFIG = {
  // Network errors - always retry
  network: {
    enabled: true,
    maxAttempts: 3,
    baseDelay: 1000,
    maxDelay: 10000,
    backoffMultiplier: 2
  },
  
  // Timeout errors - retry with increased timeout
  timeout: {
    enabled: true,
    maxAttempts: 2,
    baseDelay: 2000,
    maxDelay: 15000,
    backoffMultiplier: 2
  },
  
  // Server errors (5xx) - limited retry
  server: {
    enabled: true,
    maxAttempts: 2,
    baseDelay: 3000,
    maxDelay: 20000,
    backoffMultiplier: 2
  },
  
  // Client errors (4xx) - generally don't retry
  client: {
    enabled: false,
    maxAttempts: 1,
    baseDelay: 0,
    maxDelay: 0,
    backoffMultiplier: 1
  }
} as const;

/**
 * Header names used by the API
 */
export const HEADERS = {
  RESPONSE_TIME: 'x-response-time',
  AUTHORIZATION_RESPONSE: 'x-authorization-response',
  CONTENT_TYPE: 'content-type'
} as const;

/**
 * Authorization response values
 */
export const AUTH_STATUS = {
  OK: 'ok',
  UNAUTHORIZED: 'unauthorized'
} as const;

/**
 * Create a configuration by merging defaults with environment-specific and custom options
 */
export function createConfig(
  baseConfig: ClientConfig,
  customConfig?: Partial<Omit<ClientConfig, 'baseUrl'>>
): Required<ClientConfig> {
  return {
    ...DEFAULT_CONFIG,
    ...baseConfig,
    ...customConfig,
    headers: {
      ...DEFAULT_CONFIG.headers,
      ...baseConfig.headers,
      ...customConfig?.headers
    }
  };
}

/**
 * Create a configuration from environment and custom options
 */
export function createConfigFromEnvironment(
  environment: string,
  customConfig?: Partial<ClientConfig>
): Required<ClientConfig> {
  const envConfig = ENVIRONMENT_CONFIGS[environment];
  if (!envConfig) {
    throw new Error(`Unknown environment: ${environment}. Available environments: ${Object.keys(ENVIRONMENT_CONFIGS).join(', ')}`);
  }
  
  return {
    ...DEFAULT_CONFIG,
    ...envConfig,
    ...customConfig,
    headers: {
      ...DEFAULT_CONFIG.headers,
      ...envConfig.headers,
      ...customConfig?.headers
    }
  };
}

/**
 * Get timeout for a specific endpoint
 */
export function getEndpointTimeout(endpoint: string, defaultTimeout: number): number {
  // Remove path parameters for matching
  const normalizedEndpoint = endpoint.replace(/\/\d+/g, '/{id}').replace(/\/[^/]+$/g, '/{param}');
  
  return ENDPOINT_TIMEOUTS[normalizedEndpoint as keyof typeof ENDPOINT_TIMEOUTS] || defaultTimeout;
}

/**
 * Validate configuration
 */
export function validateConfig(config: ClientConfig): string[] {
  const errors: string[] = [];
  
  if (config.baseUrl && !isValidUrl(config.baseUrl)) {
    errors.push('baseUrl must be a valid URL');
  }
  
  if (config.timeout && (config.timeout <= 0 || config.timeout > 300000)) {
    errors.push('timeout must be between 1ms and 300s (5 minutes)');
  }
  
  if (config.retries && (config.retries < 0 || config.retries > 10)) {
    errors.push('retries must be between 0 and 10');
  }
  
  if (config.retryDelay && (config.retryDelay < 0 || config.retryDelay > 60000)) {
    errors.push('retryDelay must be between 0ms and 60s');
  }
  
  if (config.logLevel && !['debug', 'info', 'warn', 'error'].includes(config.logLevel)) {
    errors.push('logLevel must be one of: debug, info, warn, error');
  }
  
  return errors;
}

/**
 * Check if a string is a valid URL
 */
function isValidUrl(urlString: string): boolean {
  try {
    const url = new URL(urlString);
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch {
    return false;
  }
}

/**
 * Get the full API URL for an endpoint
 */
export function getApiUrl(baseUrl: string, endpoint: string): string {
  const cleanBaseUrl = baseUrl.replace(/\/$/, '');
  const cleanEndpoint = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
  return `${cleanBaseUrl}${API_BASE_PATH}${cleanEndpoint}`;
}

/**
 * Replace path parameters in endpoint URLs
 */
export function replacePathParams(endpoint: string, params: Record<string, string | number>): string {
  let result = endpoint;
  
  for (const [key, value] of Object.entries(params)) {
    result = result.replace(`{${key}}`, String(value));
  }
  
  return result;
}

/**
 * Build query string from parameters
 */
export function buildQueryString(params: Record<string, string | number | boolean | undefined>): string {
  const filtered = Object.entries(params)
    .filter(([, value]) => value !== undefined && value !== null)
    .map(([key, value]) => [key, String(value)]);
  
  if (filtered.length === 0) {
    return '';
  }
  
  const searchParams = new URLSearchParams();
  filtered.forEach(([key, value]) => {
    searchParams.append(key, value);
  });
  return `?${searchParams.toString()}`;
}