<?php
if ( ! defined( 'ABSPATH' ) ) exit;

/**
 * HTTP 呼出の共通ヘルパ
 *
 * プラグイン内 33 箇所で散在していた wp_remote_post / wp_remote_get の定型処理
 * (timeout 指定、headers 構築、is_wp_error チェック、response_code/body 取得、
 * JSON デコード) を集約。各 call site の重複コードを約 4-5 行 → 1 行呼び出しに短縮。
 *
 * 戻り値の構造を統一することで、API 呼出ロジックを単純化:
 *   - 成功時: array( 'code' => int, 'body' => string, 'json' => mixed|null, ... )
 *   - 失敗時: WP_Error (is_wp_error() で判定可能)
 *
 * call_with_retry とは独立に動作。リトライが必要な箇所は引き続き
 * AIAP_AI_Client::generate_with_retry / AIAP_Image_Providers::call_with_retry
 * の callable 内で AIAP_Http を呼ぶ。
 */
class AIAP_Http {

    /**
     * JSON POST リクエスト
     *
     * 主に AI API (Claude / OpenAI / Gemini / Imagen / Stability / Flux 等) への
     * リクエスト送信に使用。body を自動で wp_json_encode し、Content-Type: application/json
     * を自動付与する。
     *
     * @param string $url     リクエスト先 URL
     * @param array  $body    リクエストボディ (配列のまま渡す。内部で wp_json_encode)
     * @param array  $headers 追加ヘッダ (Authorization など)。Content-Type は自動付与
     * @param int    $timeout タイムアウト秒数 (デフォルト 120 秒、AI 生成系を想定)
     * @return array|WP_Error 成功時: ['code' => int, 'body' => string, 'json' => mixed|null, 'response' => array]
     *                        失敗時: WP_Error
     *                        'response' は元の wp_remote_post の戻り値そのまま
     *                        (AIAP_AI_Errors::build_api_error_wp_error などで利用するため残す)
     */
    public static function post_json( $url, $body, $headers = array(), $timeout = 120 ) {
        $response = wp_remote_post( $url, array(
            'timeout' => $timeout,
            'headers' => array_merge(
                array( 'Content-Type' => 'application/json' ),
                $headers
            ),
            'body' => wp_json_encode( $body ),
        ) );
        if ( is_wp_error( $response ) ) {
            return $response;
        }
        $text = wp_remote_retrieve_body( $response );
        return array(
            'code'     => (int) wp_remote_retrieve_response_code( $response ),
            'body'     => $text,
            'json'     => json_decode( $text, true ),
            'response' => $response,
        );
    }

    /**
     * GET リクエスト
     *
     * モデル一覧取得、画像ダウンロード、外部 API クエリなどに使用。
     * headers が空の場合は headers キーを送信しない (元コードとの互換のため)。
     *
     * @param string $url     リクエスト先 URL
     * @param array  $headers 追加ヘッダ (空なら未指定)
     * @param int    $timeout タイムアウト秒数 (デフォルト 20 秒、メタ情報取得を想定)
     * @return array|WP_Error 成功時: ['code' => int, 'body' => string, 'json' => mixed|null, 'response' => array]
     *                        失敗時: WP_Error
     *                        'response' は元の wp_remote_get の戻り値そのまま (画像 DL 等で必要な場合用)
     */
    public static function get( $url, $headers = array(), $timeout = 20 ) {
        $args = array( 'timeout' => $timeout );
        if ( ! empty( $headers ) ) {
            $args['headers'] = $headers;
        }
        $response = wp_remote_get( $url, $args );
        if ( is_wp_error( $response ) ) {
            return $response;
        }
        $text = wp_remote_retrieve_body( $response );
        return array(
            'code'     => (int) wp_remote_retrieve_response_code( $response ),
            'body'     => $text,
            'json'     => json_decode( $text, true ),
            'response' => $response,
        );
    }

    /**
     * Bearer 認証ヘッダを生成 (OpenAI / Stability / Flux など多数の API で共通)
     *
     * @param string $token API トークン
     * @return array ['Authorization' => 'Bearer xxx']
     */
    public static function bearer( $token ) {
        return array( 'Authorization' => 'Bearer ' . $token );
    }

    /**
     * x-api-key 認証ヘッダを生成 (Anthropic Claude 等で使用)
     *
     * @param string $key API キー
     * @return array ['x-api-key' => 'xxx']
     */
    public static function x_api_key( $key ) {
        return array( 'x-api-key' => $key );
    }
}
