<?php

namespace Itmar\SNS\Tool;

use WP_Error;

class HttpTool
{
    /**
     * 外部URLのファイルを一時ダウンロードし、テンポラリファイルパスを返す
     */
    public static function download_to_temp($url)
    {
        $response = wp_remote_get($url, ['sslverify' => true]);
        if (is_wp_error($response)) return $response;

        $body = wp_remote_retrieve_body($response);
        if (!$body) return new WP_Error('Error', 'リモートファイルの取得に失敗しました');

        $tmp_file = wp_tempnam($url);
        if (!$tmp_file) {
            return new WP_Error('Errror', '一時ファイルの作成に失敗しました');
        }

        file_put_contents($tmp_file, $body);
        return $tmp_file;
    }

    /**
     * /presign を叩いて PUT用またはGET用のURLとS3パスをもらう
     */
    public static function presign_request($op)
    {
        $api_base = rtrim(ITMAR_AWS_BASE_URL, '/');
        //$token    = (string) get_option('lambda_api_token');

        $body_arr = wp_json_encode(
            [
                'ext' => $op['ext'],
                'type' => $op['type'],
                'op' => $op['op'],
                'bucket' => $op['bucket'] ?? '',
                'key' => $op['key'] ?? '',
                'out_key' => $op['out_key'] ?? '',
                'params' => $op['params'] ?? '',
                'ig_user_id' => $op['ig_user_id'] ?? '',
                'wp_id' => $op['wp_id'] ?? '',
                'caption' => $op['caption'],
                'expires' => 900,
            ],
            JSON_UNESCAPED_SLASHES
        );

        $res = wp_remote_post("$api_base/presign", [
            'headers' => array_filter([
                'Content-Type' => 'application/json',
                'X-FB-Token'  => $op['fb_token'],
                'X-Site-Url'      => home_url()
            ]),
            'body'    => $body_arr,
            'timeout' => 30,
        ]);


        if (is_wp_error($res)) return $res;

        $code = wp_remote_retrieve_response_code($res);
        $body = json_decode(wp_remote_retrieve_body($res), true);
        return ($code === 200 && is_array($body))
            ? $body
            : new WP_Error('presign_failed', 'presign failed: ' . $code . ' ' . print_r($body, true));
    }
    /**
     * /jobs を叩いて 投稿結果をもらう
     */
    public static function jobs_result_request()
    {
        $api_base = rtrim(ITMAR_AWS_BASE_URL, '/');
        $site_url = home_url();

        $r = wp_remote_get("$api_base/jobs?site_url=" . urlencode($site_url), ['timeout' => 15]);

        if (is_wp_error($r)) {
            $ret_str = 'ERROR,結果取得失敗: ' . $r->get_error_message();
            return new WP_Error($ret_str);
        }
        $rc   = wp_remote_retrieve_response_code($r);
        $body = json_decode(wp_remote_retrieve_body($r), true);
        return ($rc === 200 && is_array($body))
            ? $body
            : new WP_Error('jobs_failed', 'jobs failed: ' . $rc . ' ' . print_r($body, true));
    }

    /**
     * 署名付きPUT URLに動画をアップロード
     */
    public static function put_upload(string $put_url, string $source, $headers = null)
    {
        // 署名に Content-Type を含めていない場合は、余計なヘッダーを付けない方が安全
        // 必要なら呼び出し側で ['Content-Type' => 'video/mp4'] を渡してください。
        $headers = $headers ?? [];
        // ---- WP_Filesystem 初期化 ----
        if (! function_exists('WP_Filesystem')) {
            require_once ABSPATH . 'wp-admin/includes/file.php';
        }

        $creds_ok = WP_Filesystem(); // ローカル環境では通常true。FTPが必要な環境では資格情報ダイアログになることも
        if (! $creds_ok) {
            return new WP_Error('fs_init_failed', 'WP_Filesystem の初期化に失敗しました。');
        }
        global $wp_filesystem;

        // ---- 送信バイト列を用意（URLは一時DL→読み込み / ローカルは直接読み込み）----
        $is_url = (bool) preg_match('#^https?://#i', $source);
        $tmp    = null;
        $bytes  = null;

        if ($is_url) {
            // WordPressのダウンロードユーティリティ（HTTP APIで取得→一時ファイル保存）
            $tmp = self::temp_download($source, 300); // タイムアウト300秒
            if (is_wp_error($tmp)) {
                return new WP_Error('download_failed', '元URLの取得に失敗: ' . $tmp->get_error_message());
            }
            // 一時ファイルの内容をWP_Filesystemで読む（メモリに展開される点に注意）
            $bytes = $wp_filesystem->get_contents($tmp);
            wp_delete_file($tmp);
            if ($bytes === false) {
                return new WP_Error('read_failed', '一時ファイルの読み込みに失敗しました。');
            }
        } else {
            if (! $wp_filesystem->exists($source)) {
                return new WP_Error('file_missing', 'アップロード元ファイルがありません。');
            }
            $bytes = $wp_filesystem->get_contents($source);
            if ($bytes === false) {
                return new WP_Error('read_failed', 'ファイルの読み込みに失敗しました。');
            }
        }

        // ---- PUT 実行（WordPress HTTP API）----
        $resp = wp_remote_request($put_url, [
            'method'      => 'PUT',
            'headers'     => $headers,              // 例: ['Content-Type' => 'video/mp4', 'Expect' => '']
            'body'        => $bytes,                // ※全体をメモリに乗せて送信
            'timeout'     => 900,                   // 大きめ
            'blocking'    => true,
            'redirection' => 5,
            'reject_unsafe_urls' => true,
            // ← ここに CA バンドルを明示
            'sslverify'        => true,
            //'sslcertificates'  => WP_CONTENT_DIR . '/uploads/certs/cacert_merged.pem', //ローカルのcacert_merged.pemを使用、本番では//
        ]);

        if (is_wp_error($resp)) {
            return new WP_Error('http_error', $resp->get_error_message());
        }

        $code = wp_remote_retrieve_response_code($resp);
        $body = wp_remote_retrieve_body($resp);
        if ($code < 200 || $code >= 300) {
            return new WP_Error('put_failed', sprintf('PUT失敗: HTTP %d: %s', $code, mb_substr((string) $body, 0, 500)));
        }

        return true;
    }
    //一時ファイルを生成する（ローカルのcacert_merged.pemを使用、本番では削除）
    private static function temp_download(string $url, int $timeout = 300)
    {
        $tmp = wp_tempnam('upload-src-');
        if (!$tmp) return new WP_Error('temp_failed', '一時ファイルを作成できません。');

        $args = [
            'timeout'     => $timeout,
            'stream'      => true,
            'filename'    => $tmp,
            'redirection' => 5,
            // ← ここに CA バンドルを明示
            'sslverify'        => false, //本番サーバーでは　trueにすること
            //'sslcertificates'  => WP_CONTENT_DIR . '/uploads/certs/cacert_merged.pem',
        ];

        $res = wp_remote_get($url, $args);
        if (is_wp_error($res)) {
            wp_delete_file($tmp);
            return $res;
        }
        $code = wp_remote_retrieve_response_code($res);
        if ($code < 200 || $code >= 300) {
            wp_delete_file($tmp);
            return new WP_Error('download_bad_status', "HTTP $code");
        }
        return $tmp;
    }

    //S3にアップロードして署名付きGET URLを取得
    public static function upload_to_s3($source_url, $post_data)
    {
        //拡張子の取得
        $path = wp_parse_url($source_url, PHP_URL_PATH);
        $file = basename($path);
        $ft = wp_check_filetype($file);

        //動画変換先パスを設定(変換要請ありのときだけ)
        $out_key = is_array($post_data) ? 'converted/' . wp_generate_uuid4() . '.mp4' : "";
        //トークンは取得する
        $token = is_array($post_data) ? $post_data['access_token'] : $post_data;
        //動画変換パラメーター
        $params = is_array($post_data) ?
            wp_json_encode([
                'width'           => 1080,
                'height'          => 1920,
                'fps'             => 30,
                'video_bitrate'   => '5M',
                'audio_bitrate'   => '128k',
                'audio_samplerate' => 44100,
                'timeout_sec'     => 1800,
            ], JSON_UNESCAPED_SLASHES)
            : "";

        //AWS S3 署名付き put_urlを要求
        $put_op = [
            'op' => 'put',
            'ext' => $ft['ext'],
            'type' => $ft['type'],
            'out_key' => $out_key,
            'params' => $params,
            'wp_id' => is_array($post_data) ? $post_data['id'] : '',
            'caption' => is_array($post_data) ? $post_data['caption'] : '',
            'ig_user_id' => is_array($post_data) ? $post_data['ig_user_id'] : '',
            'fb_token' => $token
        ];
        $put = self::presign_request($put_op);

        // 署名付きURLを発行する側（サーバ）でも Tagging を含めて署名しておくこと（重要）
        $headers = $put['required_headers'];  // ← 返ってきたものをそのまま使う
        //S3への登録開始
        $result = self::put_upload(
            $put['put_url'],
            $source_url,
            $headers
        );

        if (is_array($post_data)) { //$post_dataが配列で与えられているときは変換要請あり
            //変換要請ありのときは結果を返すだけ
            return $result;
        } else {
            if (!is_wp_error($result)) {
                //AWS S3 署名付き get_urlを要求
                $get_op = [
                    'op' => 'get',
                    'bucket' => $put['bucket'],
                    'key' => $put['key'],
                    'ext' => $ft['ext'],
                    'type' => $ft['type']
                ];
                return self::presign_request($get_op);
            } else {
                return false;
            }
        }
    }


    //WP_POSTMETAへの結果の記録
    public static function rec_result($id, $ret_id_name, $ret_val)
    {
        // 結果が WP_Error ならメッセージを保存、それ以外は$ret_valをそのまま保存
        if (is_wp_error($ret_val)) {
            $error_message = $ret_val->get_error_message();
            $result = update_post_meta($id, $ret_id_name, 'ERROR,' . $error_message);
        } else {
            $result = update_post_meta($id, $ret_id_name, $ret_val);
        }
        return $result;
    }
}
