import { BaseEndpoint } from '../base';
import { 
  PredictRequest, 
  PredictResponse, 
  PredictConfigResponse,
  DecideRequest,
  DecideResponse
} from './types';
import { InvalidRequestError, AuthenticationError, ServerError } from '../../errors';

export class IntelligenceEndpoint extends BaseEndpoint {
  constructor(client: any) {
    super(client, '/api/intelligence');
  }

  private validateRequiredKeys(data: { organization_apikey?: string; app_apikey?: string }) {
    if (!data.organization_apikey) {
      throw new InvalidRequestError('organization_apikey is required');
    }
    if (!data.app_apikey) {
      throw new InvalidRequestError('app_apikey is required');
    }
  }

  /**
   * Get prediction configuration and available options
   * @returns Promise with the prediction configuration
   * @throws {AuthenticationError} If API keys are invalid
   * @throws {ServerError} If server encounters an error
   */
  async getPredictConfig(): Promise<PredictConfigResponse> {
    try {
      return await this.get<PredictConfigResponse>('/predict/config');
    } catch (error: any) {
      if (error.response?.status === 401) {
        throw new AuthenticationError('Invalid API keys');
      }
      if (error.response?.status === 500) {
        throw new ServerError('Internal server error');
      }
      throw error;
    }
  }

  /**
   * Get a prediction for an item
   * @param data - The prediction request parameters
   * @returns Promise with the prediction response
   * @throws {InvalidRequestError} If required fields are missing or invalid
   * @throws {AuthenticationError} If API keys are invalid
   * @throws {ServerError} If server encounters an error
   */
  async predict(data: PredictRequest): Promise<PredictResponse> {
    this.validateRequiredKeys(data);

    if (!data.item_id) {
      throw new InvalidRequestError('item_id is required');
    }
    if (!data.prediction_type) {
      throw new InvalidRequestError('prediction_type is required');
    }
    if (!data.timeframe) {
      throw new InvalidRequestError('timeframe is required');
    }

    try {
      return await this.post<PredictResponse>('/predict', data);
    } catch (error: any) {
      if (error.response?.status === 400) {
        throw new InvalidRequestError(error.response.data?.message || 'Invalid request');
      }
      if (error.response?.status === 401) {
        throw new AuthenticationError('Invalid API keys');
      }
      if (error.response?.status === 500) {
        throw new ServerError('Internal server error');
      }
      throw error;
    }
  }

  /**
   * Get a decision based on log data
   * @param data - The decision request parameters
   * @returns Promise with the decision response
   * @throws {InvalidRequestError} If required fields are missing or invalid
   * @throws {AuthenticationError} If API keys are invalid
   * @throws {ServerError} If server encounters an error
   */
  async decide(data: DecideRequest): Promise<DecideResponse> {
    this.validateRequiredKeys(data);

    if (!data.log_data) {
      throw new InvalidRequestError('log_data is required');
    }
    if (!data.log_data.metrics || !Array.isArray(data.log_data.metrics) || data.log_data.metrics.length === 0) {
      throw new InvalidRequestError('log_data.metrics must be a non-empty array');
    }
    if (!data.log_data.context) {
      throw new InvalidRequestError('log_data.context is required');
    }
    if (!data.log_data.item_name) {
      throw new InvalidRequestError('log_data.item_name is required');
    }
    if (!data.allowed_actions || Object.keys(data.allowed_actions).length === 0) {
      throw new InvalidRequestError('allowed_actions must be a non-empty object');
    }

    try {
      return await this.post<DecideResponse>('/decide', data);
    } catch (error: any) {
      if (error.response?.status === 400) {
        throw new InvalidRequestError(error.response.data?.message || 'Invalid request');
      }
      if (error.response?.status === 401) {
        throw new AuthenticationError('Invalid API keys');
      }
      if (error.response?.status === 500) {
        throw new ServerError('Internal server error');
      }
      throw error;
    }
  }
} 