/**
 * Plan service module for handling plan and claim data loading.
 * Provides functionality to load plans with retry mechanism and error handling.
 *
 * @module plan
 */

import axios from "axios";
import { logger } from "../utils/logger";

/**
 * Response interface for plan loading operations.
 * Represents the structure of both successful and error responses.
 */
interface PlanResponse {
  /** The response data payload */
  data?: unknown;
  /** HTTP status code of the response */
  status?: number;
  /** Error message in case of failure */
  error?: string;
  /** Response headers */
  headers?: unknown;
}

/**
 * Loads a plan with automatic retry mechanism.
 * Attempts to load the plan multiple times in case of failure.
 *
 * @param handle - The unique identifier for the plan or claim
 * @param retries - Number of retry attempts (default: 3)
 * @returns Promise resolving to PlanResponse
 *
 * @remarks
 * - Implements exponential backoff with 1 second delay between retries
 * - Provides detailed logging of each attempt and any errors
 * - Handles both plan and claim flows based on handle content
 * - Logs comprehensive error information including:
 *   - HTTP status and headers
 *   - Response data
 *   - Request configuration
 *
 * @example
 * ```typescript
 * const response = await loadPlanWithRetry('plan-123');
 * if (response.error) {
 *   console.error(response.error);
 * } else {
 *   console.log(response.data);
 * }
 * ```
 */
export const loadPlanWithRetry = async (
  handle: string,
  retries = 3,
): Promise<PlanResponse> => {
  try {
    logger.log(`[Plan Service] Loading plan ${handle}, attempt 1/${retries}`);
    logger.log(
      `[Plan Service] Context: Deep link handle=${handle}, isClaimFlow=${handle.includes("claim")}`,
    );

    // Different endpoint if this is a claim flow
    const response = await loadPlan(handle);
    logger.log(`[Plan Service] Plan ${handle} loaded successfully:`, {
      status: response?.status,
      headers: response?.headers,
      data: response?.data,
    });

    return response;
  } catch (error: unknown) {
    logger.error(`[Plan Service] Error loading plan ${handle}:`, {
      message: (error as Error).message,
      status: (error as { response?: { status?: number } })?.response?.status,
      statusText: (error as { response?: { statusText?: string } })?.response
        ?.statusText,
      data: (error as { response?: { data?: unknown } })?.response?.data,
      headers: (error as { response?: { headers?: unknown } })?.response
        ?.headers,
      config: {
        url: (error as { config?: { url?: string } })?.config?.url,
        method: (error as { config?: { method?: string } })?.config?.method,
        baseURL: (error as { config?: { baseURL?: string } })?.config?.baseURL,
        headers: (error as { config?: { headers?: unknown } })?.config?.headers,
      },
    });

    if (retries > 1) {
      logger.log(
        `[Plan Service] Retrying plan ${handle}, ${retries - 1} attempts remaining`,
      );
      await new Promise((resolve) => setTimeout(resolve, 1000));
      return loadPlanWithRetry(handle, retries - 1);
    }

    return {
      error: `Failed to load plan ${handle} after ${4 - retries} attempts: ${(error as Error).message}`,
      status: (error as { response?: { status?: number } })?.response?.status,
    };
  }
};

/**
 * Makes a single API request to load a plan or claim.
 * Determines the appropriate endpoint based on the handle.
 *
 * @param handle - The unique identifier for the plan or claim
 * @returns Promise resolving to PlanResponse
 * @throws Will throw an error if the API request fails
 *
 * @remarks
 * - Automatically detects claim vs plan endpoints based on handle
 * - Uses axios for HTTP requests
 * - Provides detailed error logging
 * - Different endpoints:
 *   - Claims: /api/claims/{handle}
 *   - Plans: /api/plans/{handle}
 */
export const loadPlan = async (handle: string): Promise<PlanResponse> => {
  logger.log(`[Plan Service] Making API request for plan ${handle}`);

  const endpoint = handle.includes("claim")
    ? `/api/claims/${handle}`
    : `/api/plans/${handle}`;

  logger.log(`[Plan Service] Using endpoint: ${endpoint}`);

  try {
    const response = await axios.get(endpoint);
    return response;
  } catch (error: unknown) {
    logger.error(`[Plan Service] API request failed for ${handle}:`, {
      endpoint,
      error: (error as Error).message,
      response: (error as { response?: { data?: unknown } })?.response?.data,
    });
    throw error;
  }
};
