/**
 * Unified Error Handling for Portal
 *
 * Clean, simple error handling that uses shared error codes from domain package.
 * Provides consistent error parsing and user-friendly messages.
 */

import { ApiError as ClientApiError, isApiError, parseDomainError } from "@/core/api";
import {
  ErrorCode,
  ErrorMessages,
  ErrorMetadata,
  mapHttpStatusToErrorCode,
  type ErrorCodeType,
} from "@customer-portal/domain/common";

// ============================================================================
// Types
// ============================================================================

export interface ParsedError {
  code: ErrorCodeType;
  message: string;
  shouldLogout: boolean;
  shouldRetry: boolean;
}

// ============================================================================
// Error Parsing
// ============================================================================

/**
 * Parse any error into a structured format with code and user-friendly message.
 * This is the main entry point for error handling.
 */
export function parseError(error: unknown): ParsedError {
  // Handle API client errors
  if (isApiError(error)) {
    return parseApiError(error);
  }

  // Handle network/fetch errors
  if (error instanceof Error) {
    return parseNativeError(error);
  }

  // Handle string errors
  if (typeof error === "string") {
    return {
      code: ErrorCode.UNKNOWN,
      message: error,
      shouldLogout: false,
      shouldRetry: true,
    };
  }

  // Unknown error type
  return {
    code: ErrorCode.UNKNOWN,
    message: ErrorMessages[ErrorCode.UNKNOWN],
    shouldLogout: false,
    shouldRetry: true,
  };
}

/**
 * Parse API client error
 */
function parseApiError(error: ClientApiError): ParsedError {
  const body = error.body;
  const status = error.response?.status;

  const domainError = parseDomainError(body);
  if (domainError) {
    const rawCode = domainError.error.code;
    const resolvedCode: ErrorCodeType = Object.prototype.hasOwnProperty.call(ErrorMetadata, rawCode)
      ? (rawCode as ErrorCodeType)
      : ErrorCode.UNKNOWN;

    const metadata = ErrorMetadata[resolvedCode] ?? ErrorMetadata[ErrorCode.UNKNOWN];
    return {
      code: resolvedCode,
      message: domainError.error.message,
      shouldLogout: metadata.shouldLogout,
      shouldRetry: metadata.shouldRetry,
    };
  }

  // Fall back to status code mapping
  const code = mapHttpStatusToErrorCode(status);
  const metadata = ErrorMetadata[code];
  return {
    code,
    message: error.message || ErrorMessages[code],
    shouldLogout: metadata.shouldLogout,
    shouldRetry: metadata.shouldRetry,
  };
}

/**
 * Parse native JavaScript errors (network, timeout, etc.)
 */
function parseNativeError(error: Error): ParsedError {
  // Network errors
  if (error.name === "TypeError" && error.message.includes("fetch")) {
    return {
      code: ErrorCode.NETWORK_ERROR,
      message: ErrorMessages[ErrorCode.NETWORK_ERROR],
      shouldLogout: false,
      shouldRetry: true,
    };
  }

  // Timeout errors
  if (error.name === "AbortError") {
    return {
      code: ErrorCode.TIMEOUT,
      message: ErrorMessages[ErrorCode.TIMEOUT],
      shouldLogout: false,
      shouldRetry: true,
    };
  }

  return {
    code: ErrorCode.UNKNOWN,
    message: error.message || ErrorMessages[ErrorCode.UNKNOWN],
    shouldLogout: false,
    shouldRetry: true,
  };
}

// ============================================================================
// Convenience Functions
// ============================================================================

/**
 * Get user-friendly error message from any error
 */
export function getErrorMessage(error: unknown): string {
  return parseError(error).message;
}

/**
 * Check if error should trigger logout
 */
export function shouldLogout(error: unknown): boolean {
  return parseError(error).shouldLogout;
}

// ============================================================================
// Re-exports from domain package for convenience
// ============================================================================

export {
  ErrorCode,
  ErrorMessages,
  ErrorMetadata,
  type ErrorCodeType,
} from "@customer-portal/domain/common";
