/**
 * API Client with Validation
 * FE-TYPE-002: Enhanced API client methods with automatic Zod validation
 * 
 * Provides typed API client methods that automatically validate responses
 * using Zod schemas.
 */

import { AxiosResponse } from 'axios';
import { z } from 'zod';
import { apiClient } from './client';
import { safeValidateApiResponse } from '@/schemas/apiSchemas';
import { safeValidateApiRequest } from '@/schemas/apiRequestSchemas';
import { logger } from '@/utils/logger';

// Extend InternalAxiosRequestConfig to include validation schemas
interface ValidatedRequestConfig {
  _requestSchema?: z.ZodSchema;
  _responseSchema?: z.ZodSchema;
  [key: string]: any;
}

/**
 * Create a validated API request
 * 
 * @param requestFn - Function that makes the API request
 * @param schema - Zod schema to validate the response
 * @param options - Validation options
 * @returns Validated response
 */
export async function validatedRequest<T>(
  requestFn: () => Promise<AxiosResponse<T>>,
  schema: z.ZodSchema<T>,
  options: {
    throwOnError?: boolean;
  } = {},
): Promise<T> {
  const { throwOnError = false } = options;

  const response = await requestFn();
  const validation = safeValidateApiResponse(schema, response.data);

  if (!validation.success) {
    const errorMessage = `API response validation failed: ${validation.error?.errors.map(e => e.message).join(', ')}`;
    logger.error('[API Validation]', {
      errors: validation.error?.errors,
      data: response.data,
    });

    if (throwOnError) {
      throw new Error(errorMessage);
    }

    // In development, log warning but continue
    if (import.meta.env.DEV) {
      console.warn('[API Validation Warning]', validation.error);
    }
  }

  // Return validated data if validation succeeded, otherwise return original data
  return validation.data ?? (response.data as T);
}

/**
 * Validated API client methods
 * Automatically validates responses using provided schemas
 */
export const validatedApiClient = {
  /**
   * GET request with validation
   */
  get: <T = any>(
    url: string,
    schema: z.ZodSchema<T>,
    config?: ValidatedRequestConfig,
  ): Promise<T> => {
    return validatedRequest(
      () => apiClient.get<T>(url, { ...config, _responseSchema: schema } as any),
      schema,
    );
  },

  /**
   * GET request with request params validation
   */
  getWithParams: <T = any, P = any>(
    url: string,
    paramsSchema: z.ZodSchema<P>,
    responseSchema: z.ZodSchema<T>,
    params?: P,
    config?: ValidatedRequestConfig,
  ): Promise<T> => {
    // Validate params
    if (params) {
      const validation = safeValidateApiRequest(paramsSchema, params);
      if (!validation.success) {
        throw new Error(`Request params validation failed: ${validation.error?.errors.map(e => e.message).join(', ')}`);
      }
      params = validation.data;
    }
    return validatedRequest(
      () => apiClient.get<T>(url, { ...config, params, _responseSchema: responseSchema } as any),
      responseSchema,
    );
  },

  /**
   * POST request with validation
   */
  post: <T = any, D = any>(
    url: string,
    data?: D,
    requestSchema?: z.ZodSchema<D>,
    responseSchema?: z.ZodSchema<T>,
    config?: ValidatedRequestConfig,
  ): Promise<T> => {
    // Validate request data if schema provided
    let validatedData = data;
    if (requestSchema && data !== undefined && data !== null) {
      const validation = safeValidateApiRequest(requestSchema, data);
      if (!validation.success) {
        throw new Error(`Request validation failed: ${validation.error?.errors.map(e => e.message).join(', ')}`);
      }
      validatedData = validation.data;
    }

    if (!responseSchema) {
      // If no response schema provided, use regular client
      return apiClient.post<T>(url, validatedData, { ...config, _requestSchema: requestSchema } as any).then((res) => res.data);
    }
    return validatedRequest(
      () => apiClient.post<T>(url, validatedData, { ...config, _requestSchema: requestSchema, _responseSchema: responseSchema } as any),
      responseSchema,
    );
  },

  /**
   * PUT request with validation
   */
  put: <T = any>(
    url: string,
    data?: any,
    schema?: z.ZodSchema<T>,
    config?: ValidatedRequestConfig,
  ): Promise<T> => {
    if (!schema) {
      return apiClient.put<T>(url, data, config as any).then((res) => res.data);
    }
    return validatedRequest(
      () => apiClient.put<T>(url, data, { ...config, _responseSchema: schema } as any),
      schema,
    );
  },

  /**
   * PATCH request with validation
   */
  patch: <T = any>(
    url: string,
    data?: any,
    schema?: z.ZodSchema<T>,
    config?: ValidatedRequestConfig,
  ): Promise<T> => {
    if (!schema) {
      return apiClient.patch<T>(url, data, config as any).then((res) => res.data);
    }
    return validatedRequest(
      () => apiClient.patch<T>(url, data, { ...config, _responseSchema: schema } as any),
      schema,
    );
  },

  /**
   * DELETE request with validation
   */
  delete: <T = any>(
    url: string,
    schema?: z.ZodSchema<T>,
    config?: ValidatedRequestConfig,
  ): Promise<T> => {
    if (!schema) {
      return apiClient.delete<T>(url, config as any).then((res) => res.data);
    }
    return validatedRequest(
      () => apiClient.delete<T>(url, { ...config, _responseSchema: schema } as any),
      schema,
    );
  },
};

