<?php
/**
 * Costudio_Error_Categorizer
 *
 * Categorizes exceptions into a fixed taxonomy for telemetry.
 *
 * Categories: rate_limit | overload | grounding | image | publish | other
 *
 * @package Contentosapp_Studio
 * @since   3.2.0
 */

defined( 'ABSPATH' ) || exit;

class Costudio_Error_Categorizer {

    /**
     * Maps a Throwable to a standard category string.
     *
     * @param  \Throwable $e
     * @return string
     */
    public static function categorize( \Throwable $e ): string {
        $msg = strtolower( $e->getMessage() );
        if ( self::is_managed_provider_billing_error( $msg ) ) {
            return 'overload';
        }

        // 1. Check HTTP Status Code via common methods.
        $code = 0;
        if ( method_exists( $e, 'getHttpCode' ) ) {
            $code = (int) $e->getHttpCode();
        } elseif ( method_exists( $e, 'getCode' ) ) {
            $code = (int) $e->getCode();
        }

        if ( $code === 429 ) {
            return 'rate_limit';
        }
        if ( $code === 503 || $code === 504 ) {
            return 'overload';
        }

        // 2. Exception Class names.
        $class = get_class( $e );
        if ( strpos( $class, 'Grounding' ) !== false ) {
            return 'grounding';
        }

        // 3. Message content analysis.
        if ( strpos( $msg, 'rate limit' ) !== false || strpos( $msg, '429' ) !== false || strpos( $msg, 'quota' ) !== false ) {
            return 'rate_limit';
        }
        
        if ( strpos( $msg, 'overload' ) !== false || strpos( $msg, '503' ) !== false || strpos( $msg, 'unavailable' ) !== false || strpos( $msg, 'timed out' ) !== false ) {
            return 'overload';
        }

        if ( strpos( $msg, 'image' ) !== false || strpos( $msg, 'imagen' ) !== false || strpos( $msg, 'dall-e' ) !== false ) {
            return 'image';
        }

        if ( strpos( $msg, 'publish' ) !== false || strpos( $msg, 'rest api' ) !== false || strpos( $msg, 'credentials' ) !== false ) {
            return 'publish';
        }

        if ( strpos( $msg, 'grounding' ) !== false || strpos( $msg, 'sources' ) !== false ) {
            return 'grounding';
        }

        return 'other';
    }

    private static function is_managed_provider_billing_error( string $message ): bool {
        $needles = [
            'prepayment credits are depleted',
            'billing#prepay',
            'manage your project and billing',
            'project and billing',
            'managed ai provider quota or billing credits are exhausted',
            'managed ai provider needs attention',
        ];

        foreach ( $needles as $needle ) {
            if ( strpos( $message, $needle ) !== false ) {
                return true;
            }
        }

        return false;
    }
}
