<?php

namespace Itmar\SNS\Facebook;

use WP_Error;

class ApiHelper
{
    private $access_token;
    private $page_id;

    public function __construct()
    {
        $this->access_token = $this->get_selected_page_token();
        $this->page_id = $this->get_selected_page_id();
    }

    public function get_valid_access_token()
    {
        $token = get_option('itmar_facebook_access_token');
        $expires_at = get_option('itmar_facebook_expires_at');

        if ($token && $expires_at && time() < $expires_at) {
            return $token;
        }

        return $this->refresh_token_via_proxy($token);
    }

    private function refresh_token_via_proxy($old_token)
    {
        $proxy_url = ITMAR_RELAY_SERVER_PATH . '/wp-json/itmar-sns/v1/fb_refresh_token';

        $response = wp_remote_post($proxy_url, [
            'body' => [
                'old_token' => $old_token,
                'site_url'  => site_url(),
            ],
            'sslverify' => true,
        ]);

        if (is_wp_error($response)) return null;

        $body = json_decode(wp_remote_retrieve_body($response), true);
        if (!isset($body['access_token'])) return null;

        update_option('itmar_facebook_access_token', $body['access_token']);
        update_option('itmar_facebook_expires_at', time() + intval($body['expires_in'] ?? 5184000));

        return $body['access_token'];
    }

    public function get_user_info()
    {
        $user = get_option('itmar_facebook_user');
        if (!is_array($user) || empty($user['id'])) {
            delete_option('itmar_facebook_pages');
            delete_option('itmar_facebook_selected_page_id');
            return null;
        }
        return [
            'id' => $user['id'],
            'name' => $user['name'] ?? '',
            'avatar_url' => $user['avatar_url'] ?? '',
        ];
    }

    public function get_pages()
    {
        return get_option('itmar_facebook_pages', []);
    }

    public function get_selected_page_index()
    {
        return get_option('itmar_facebook_selected_page_id', '');
    }

    public function get_selected_page_id()
    {
        $pages = $this->get_pages();
        $selected_index = $this->get_selected_page_index();

        if (isset($pages[$selected_index]['id'])) {
            return $pages[$selected_index]['id'];
        }
        return null;
    }

    public function get_selected_page_token()
    {
        $pages = $this->get_pages();
        $selected_id = $this->get_selected_page_id();
        foreach ($pages as $page) {
            if ($page['id'] === $selected_id) {
                return $page['access_token'] ?? null;
            }
        }
        return null;
    }

    public function get_selected_page_name()
    {
        $pages = $this->get_pages();
        $selected_id = $this->get_selected_page_id();
        foreach ($pages as $page) {
            if ($page['id'] === $selected_id) {
                return $page['name'] ?? null;
            }
        }
        return null;
    }

    public function get_page_info()
    {
        $endpoint = "https://graph.facebook.com/v20.0/{$this->page_id}";
        $params = http_build_query([
            'access_token' => $this->access_token,
            'fields'       => 'name,link,fan_count,followers_count,picture{url}'
        ]);

        $response = wp_remote_get("{$endpoint}?{$params}");

        if (is_wp_error($response)) {
            //error_log('[FB API] ページ情報取得エラー: ' . $response->get_error_message());
            return null;
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);
        if (!isset($body['name'])) {
            //error_log('[FB API] ページ情報が取得できませんでした');
            return null;
        }

        return $body;
    }


    public function create_post($id, $text, $media_infos = [])
    {

        $has_video = false;
        $has_image = false;

        foreach ($media_infos as $media_info) {
            if ($media_info['type'] === 'video') {
                $has_video = true;
            }
            if ($media_info['type'] === 'img') {
                $has_image = true;
            }
        }

        if ($has_video && $has_image) {
            return new WP_Error('media_mixed', '画像と動画を同時に投稿することはできません。');
        }

        if ($has_video) {
            $video_id = $this->upload_video($media_infos[0]['url'], $text);
            if (is_wp_error($video_id)) {
                return $video_id;
            }
            return $video_id;
        }

        $media_fbids = [];
        foreach ($media_infos as $media_info) {
            if ($media_info['type'] === 'img') {
                $media = $this->upload_photo($media_info['url']);
                if (is_wp_error($media)) {
                    return $media;
                }
                $media_fbids[] = ['media_fbid' => $media];
            }
        }

        $post_id = $this->post_feed($text, $media_fbids);
        if (is_wp_error($post_id)) {
            return $post_id;
        }
        return $post_id;
    }


    private function upload_photo($url)
    {
        $tmp_file = $this->download_to_temp($url);
        if (is_wp_error($tmp_file)) {
            return $tmp_file;
        }

        $endpoint = "https://graph.facebook.com/v20.0/{$this->page_id}/photos";

        // ここから cURL → wp_remote_post 置き換え
        $mime     = function_exists('mime_content_type') ? mime_content_type($tmp_file) : 'application/octet-stream';
        $filename = basename($tmp_file);
        $boundary = wp_generate_password(24, false, false);
        $eol      = "\r\n";

        // 通常フィールド
        $fields = array(
            'published'    => 'false',
            'access_token' => $this->access_token,
        );

        // multipart/form-data のボディを手組み
        $body = '';
        foreach ($fields as $name => $value) {
            $body .= '--' . $boundary . $eol;
            $body .= 'Content-Disposition: form-data; name="' . $name . '"' . $eol . $eol;
            $body .= (string) $value . $eol;
        }

        // ファイルパート (name="source")
        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="source"; filename="' . $filename . '"' . $eol;
        $body .= 'Content-Type: ' . $mime . $eol . $eol;
        $body .= file_get_contents($tmp_file);
        $body .= $eol . '--' . $boundary . '--' . $eol;

        $response = wp_remote_post($endpoint, array(
            'timeout' => 30,
            'headers' => array(
                'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
            ),
            'body'    => $body,
            // 'sslverify' は既定 true のまま（審査的にも◎）
        ));

        wp_delete_file($tmp_file);

        if (is_wp_error($response)) {
            // 旧: curl_error($ch) 相当
            return $response;
        }

        $code = wp_remote_retrieve_response_code($response);
        $text = wp_remote_retrieve_body($response);
        $json = json_decode($text, true);

        if ($code < 200 || $code >= 300) {
            // Graph のエラーメッセージがあればそれを返す
            $msg = isset($json['error']['message']) ? $json['error']['message'] : 'Facebookアップロードエラー';
            return new \WP_Error('fb_upload_error', $msg, array('status' => $code, 'body' => $text));
        }

        if (isset($json['error'])) {
            return new \WP_Error('fb_upload_error', $json['error']['message'] ?? 'Facebookアップロードエラー', $json['error']);
        }

        return $json['id'] ?? new \WP_Error('fb_no_id', 'アップロードは成功しましたが ID が取得できませんでした。', $json);
    }

    private function upload_video($video_url, $description = '')
    {
        // 一時保存（既存のまま）
        $upload_path = $this->download_to_temp($video_url);
        if (is_wp_error($upload_path)) {
            return $upload_path;
        }

        $endpoint   = "https://graph.facebook.com/v20.0/{$this->page_id}/videos";
        $mime_type  = function_exists('mime_content_type') ? mime_content_type($upload_path) : 'application/octet-stream';
        $file_name  = basename($upload_path);
        $boundary   = wp_generate_password(24, false, false);
        $eol        = "\r\n";

        // 通常フィールド
        $fields = array(
            'description'  => (string) $description,
            'access_token' => $this->access_token,
        );

        // multipart/form-data のボディを生成（CURLFileの代替）
        $body = '';
        foreach ($fields as $name => $value) {
            $body .= '--' . $boundary . $eol;
            $body .= 'Content-Disposition: form-data; name="' . $name . '"' . $eol . $eol;
            $body .= (string) $value . $eol;
        }

        // ファイルパート name="source"
        $file_contents = file_get_contents($upload_path);
        if ($file_contents === false) {
            wp_delete_file($upload_path);
            return new \WP_Error('read_file_failed', '動画ファイルの読み込みに失敗しました。');
        }

        $body .= '--' . $boundary . $eol;
        $body .= 'Content-Disposition: form-data; name="source"; filename="' . $file_name . '"' . $eol;
        $body .= 'Content-Type: ' . $mime_type . $eol . $eol;
        $body .= $file_contents . $eol;
        $body .= '--' . $boundary . '--' . $eol;

        $response = wp_remote_post($endpoint, array(
            'timeout' => 120, // 動画なので長め
            'headers' => array(
                'Content-Type' => 'multipart/form-data; boundary=' . $boundary,
            ),
            'body'    => $body,
            // 'sslverify' は既定の true のまま
        ));

        // 一時ファイル削除
        wp_delete_file($upload_path);

        // エラーハンドリング
        if (is_wp_error($response)) {
            return $response;
        }

        $http_code = wp_remote_retrieve_response_code($response);
        $text      = wp_remote_retrieve_body($response);
        $json      = json_decode($text, true);

        if ($http_code < 200 || $http_code >= 300) {
            $msg = isset($json['error']['message']) ? $json['error']['message'] : '動画のアップロードに失敗しました（コード ' . $http_code . '）';
            return new \WP_Error('fb_video_upload_error', $msg, array('status' => $http_code, 'body' => $text));
        }

        if (isset($json['error'])) {
            return new \WP_Error(
                'fb_video_upload_error',
                $json['error']['message'] ?? '動画のアップロードに失敗しました',
                $json['error']
            );
        }

        return $json['id'] ?? new \WP_Error('fb_no_video_id', '動画の投稿には成功しましたが、投稿IDが取得できませんでした', $json);
    }

    private function post_feed($message, $media_fbids = [])
    {
        $endpoint = "https://graph.facebook.com/v20.0/{$this->page_id}/feed";

        $data = [
            'access_token' => $this->access_token,
            'message' => $message,
        ];

        if (!empty($media_fbids)) {
            $data['attached_media'] = json_encode($media_fbids);
        }

        $response = wp_remote_post($endpoint, [
            'timeout' => 20, //20秒まで待つ
            'body' => $data,
        ]);

        if (is_wp_error($response)) return $response;

        $body = json_decode(wp_remote_retrieve_body($response), true);

        if (isset($body['error'])) {
            return new WP_Error('fb_post_error', $body['error']['message'] ?? '投稿に失敗しました');
        }

        return $body['id'] ?? new WP_Error('fb_post_no_id', '投稿IDが取得できませんでした');
    }

    private 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('empty_body', '動画の取得に失敗しました');

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

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

    public function delete_post($post_id)
    {
        if (!$this->access_token || !$post_id) {
            return new WP_Error('no_token', 'Facebook access tokenまたは投稿IDが不正です。');
        }

        $endpoint = "https://graph.facebook.com/v20.0/{$post_id}";

        $response = wp_remote_request($endpoint, [
            'method' => 'DELETE',
            'body' => [
                'access_token' => $this->access_token,
            ],
            'timeout' => 15,
        ]);

        if (is_wp_error($response)) {
            return $response;
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);

        if (!isset($body['success']) || $body['success'] !== true) {
            $msg = $body['error']['message'] ?? 'Unknown error';
            return new WP_Error('delete_failed', "削除に失敗しました: {$msg}");
        }

        return true;
    }

    //Facebook投稿を取得
    public function get_post($limit = 10, $after_cursor = null)
    {
        $endpoint = "https://graph.facebook.com/v20.0/{$this->page_id}/posts";
        $args = [
            'access_token' => $this->access_token,
            'limit'        => $limit,
            'fields'       => 'id,message,created_time,permalink_url,full_picture,reactions.summary(true),attachments,story'
        ];

        if ($after_cursor) {
            $args['after'] = $after_cursor;
        }

        $params = http_build_query($args);
        $response = wp_remote_get("{$endpoint}?{$params}");

        if (is_wp_error($response)) {
            //error_log('[FB API] 投稿取得エラー: ' . $response->get_error_message());
            return null;
        }

        $body = json_decode(wp_remote_retrieve_body($response), true);
        if (!isset($body['data'])) {
            //error_log('[FB API] 投稿データが取得できませんでした');
            return null;
        }

        // 投稿データと次のページ用afterカーソルを返す
        return [
            'data'  => $body['data'],
            'paging' => $body['paging']['cursors']['after'] ?? null,
        ];
    }
}
