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

/**
 * SNS口コミ収集機能（Pro）
 * X/Instagram/Facebookから口コミを探し、保留→掲載するワークフローを提供する。
 */
class TMNL_SNS_Collector {

    private $x_adapter;
    private $option_key = 'tmnl_sns_accounts';

    public function __construct( $x_adapter = null ) {
        $this->x_adapter = $x_adapter;
        add_action( 'admin_menu',   array( $this, 'add_menu' ) );
        add_action( 'admin_init',   array( $this, 'handle_actions' ) );
        add_action( 'wp_ajax_tmnl_fetch_x_url', array( $this, 'ajax_fetch_x' ) );
    }

    // =========================================
    // メニュー登録
    // =========================================

    public function add_menu() {
        add_submenu_page(
            'tmnl-dashboard',
            __( 'Collect Reviews', 'kuchikomi-wall' ),
            __( '口コミ収集', 'kuchikomi-wall' ),
            'manage_options',
            'tmnl-sns-collect',
            array( $this, 'page_collect' )
        );
    }

    // =========================================
    // アクション処理
    // =========================================

    public function handle_actions() {
        if ( ! isset( $_POST['tmnl_sns_action'] ) ) return;
        if ( ! current_user_can( 'manage_options' ) ) return;

        $action = sanitize_key( $_POST['tmnl_sns_action'] );

        switch ( $action ) {
            case 'save_accounts':
                check_admin_referer( 'tmnl_save_accounts' );
                $this->save_accounts();
                wp_redirect( add_query_arg( array( 'page' => 'tmnl-sns-collect', 'saved' => '1' ), admin_url( 'admin.php' ) ) );
                exit;

            case 'add_collected':
                check_admin_referer( 'tmnl_add_collected' );
                $this->add_collected( $_POST );
                wp_redirect( add_query_arg( array( 'page' => 'tmnl-sns-collect', 'added' => '1' ), admin_url( 'admin.php' ) ) );
                exit;
        }

        // GET アクション（キュー操作）
        if ( isset( $_GET['tmnl_col_action'] ) && isset( $_GET['col_id'] ) ) {
            $col_action = sanitize_key( $_GET['tmnl_col_action'] );
            $col_id     = intval( $_GET['col_id'] );

            if ( ! wp_verify_nonce( $_GET['_tmnl_nonce'] ?? '', 'tmnl_col_' . $col_action . '_' . $col_id ) ) {
                wp_die( 'Invalid nonce' );
            }

            if ( $col_action === 'publish' ) {
                TMNL_DB::publish_testimonial( $col_id );
                wp_redirect( add_query_arg( array( 'page' => 'tmnl-sns-collect', 'published' => '1' ), admin_url( 'admin.php' ) ) );
                exit;
            }

            if ( $col_action === 'delete' ) {
                TMNL_DB::delete( $col_id );
                wp_redirect( add_query_arg( array( 'page' => 'tmnl-sns-collect', 'deleted' => '1' ), admin_url( 'admin.php' ) ) );
                exit;
            }
        }
    }

    // =========================================
    // AJAX: X URL → oEmbed 取得
    // =========================================

    public function ajax_fetch_x() {
        check_ajax_referer( 'tmnl_fetch_x', 'nonce' );

        if ( ! current_user_can( 'manage_options' ) ) {
            wp_send_json_error( array( 'message' => 'Unauthorized' ) );
        }

        $url = esc_url_raw( sanitize_text_field( $_POST['url'] ?? '' ) );

        if ( empty( $url ) ) {
            wp_send_json_error( array( 'message' => '無効なURLです。' ) );
        }

        if ( ! $this->x_adapter ) {
            wp_send_json_error( array( 'message' => 'X アダプターが初期化されていません。' ) );
        }

        $result = $this->x_adapter->fetch_single( $url );

        if ( is_wp_error( $result ) ) {
            wp_send_json_error( array( 'message' => $result->get_error_message() ) );
        }

        // HTMLからテキストを抽出
        $text = '';
        if ( ! empty( $result['html'] ) ) {
            if ( preg_match( '/<p[^>]*>(.*?)<\/p>/is', $result['html'], $m ) ) {
                $text = wp_strip_all_tags( $m[1] );
                $text = html_entity_decode( $text, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
                // 末尾のアカウント部分（&mdash; 〜）を除去
                $text = preg_replace( '/—.*$/u', '', $text );
                $text = trim( $text );
            }
        }

        wp_send_json_success( array(
            'author_name' => $result['author_name'] ?? '',
            'text'        => $text,
            'source_url'  => $url,
        ) );
    }

    // =========================================
    // Pro判定ヘルパー
    // =========================================

    private function is_pro() {
        return kw_is_pro();
    }

    // =========================================
    // メインページ
    // =========================================

    public function page_collect() {
        if ( ! current_user_can( 'manage_options' ) ) return;

        if ( ! $this->is_pro() ) {
            $this->render_upgrade_notice();
            return;
        }

        $accounts = $this->get_accounts();
        ?>
        <div class="wrap">
            <h1><?php esc_html_e( '口コミ収集', 'kuchikomi-wall' ); ?></h1>

            <?php $this->render_notices(); ?>

            <div style="display:grid; grid-template-columns:1fr 1fr; gap:20px; margin-top:16px;">
                <div>
                    <?php $this->render_settings_section( $accounts ); ?>
                    <?php $this->render_search_section( $accounts ); ?>
                </div>
                <div>
                    <?php $this->render_add_section(); ?>
                </div>
            </div>

            <?php $this->render_queue_section(); ?>
        </div>

        <?php $this->render_js(); ?>
        <?php
    }

    // =========================================
    // セクション①：アカウント・キーワード設定
    // =========================================

    private function render_settings_section( $accounts ) {
        $x_account    = $accounts['x_account'] ?? '';
        $store_names  = implode( "\n", $accounts['store_names'] ?? array() );
        $ig_account   = $accounts['ig_account'] ?? '';
        $ig_hashtags  = implode( "\n", $accounts['ig_hashtags'] ?? array() );
        $fb_url       = $accounts['fb_url'] ?? '';
        ?>
        <div class="postbox">
            <h2 class="hndle" style="padding:12px 16px; font-size:14px;">
                <?php esc_html_e( '① アカウント・キーワード設定', 'kuchikomi-wall' ); ?>
            </h2>
            <div class="inside">
                <form method="post">
                    <?php wp_nonce_field( 'tmnl_save_accounts' ); ?>
                    <input type="hidden" name="tmnl_sns_action" value="save_accounts">
                    <table class="form-table" style="margin:0;">
                        <tr>
                            <th style="width:130px; padding:8px 10px;"><label><?php esc_html_e( 'X アカウント', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:8px 10px;">
                                <input type="text" name="x_account" value="<?php echo esc_attr( $x_account ); ?>"
                                       placeholder="@example" class="regular-text">
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:8px 10px;"><label><?php esc_html_e( '店名（検索用）', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:8px 10px;">
                                <textarea name="store_names" rows="3" class="large-text" placeholder="〇〇整体&#10;〇〇サロン&#10;（1行1パターン）"><?php echo esc_textarea( $store_names ); ?></textarea>
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:8px 10px;"><label><?php esc_html_e( 'IG アカウント', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:8px 10px;">
                                <input type="text" name="ig_account" value="<?php echo esc_attr( $ig_account ); ?>"
                                       placeholder="@example" class="regular-text">
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:8px 10px;"><label><?php esc_html_e( 'IG ハッシュタグ', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:8px 10px;">
                                <textarea name="ig_hashtags" rows="3" class="large-text" placeholder="#店名&#10;#地域名&#10;（1行1タグ）"><?php echo esc_textarea( $ig_hashtags ); ?></textarea>
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:8px 10px;"><label><?php esc_html_e( 'Facebook URL', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:8px 10px;">
                                <input type="url" name="fb_url" value="<?php echo esc_attr( $fb_url ); ?>"
                                       placeholder="https://www.facebook.com/yourpage" class="large-text">
                            </td>
                        </tr>
                    </table>
                    <div style="padding:8px 10px 12px;">
                        <?php submit_button( __( '保存', 'kuchikomi-wall' ), 'secondary small', 'submit', false ); ?>
                    </div>
                </form>
            </div>
        </div>
        <?php
    }

    // =========================================
    // セクション②：口コミを探す（検索ボタン）
    // =========================================

    private function render_search_section( $accounts ) {
        $urls = $this->build_search_urls( $accounts );
        ?>
        <div class="postbox">
            <h2 class="hndle" style="padding:12px 16px; font-size:14px;">
                <?php esc_html_e( '② 口コミを探す', 'kuchikomi-wall' ); ?>
            </h2>
            <div class="inside" style="padding-bottom:12px;">

                <p style="margin:0 0 6px; font-weight:600;">X (Twitter)</p>
                <div style="display:flex; flex-wrap:wrap; gap:6px; margin-bottom:14px;">
                    <?php foreach ( $urls['x'] as $label => $url ) : ?>
                        <a href="<?php echo esc_url( $url ); ?>" target="_blank" rel="noopener"
                           class="button button-secondary button-small">
                            <?php echo esc_html( $label ); ?> ↗
                        </a>
                    <?php endforeach; ?>
                    <?php if ( empty( $urls['x'] ) ) : ?>
                        <span class="description"><?php esc_html_e( 'Xアカウントまたは店名を設定してください。', 'kuchikomi-wall' ); ?></span>
                    <?php endif; ?>
                </div>

                <p style="margin:0 0 6px; font-weight:600;">Instagram</p>
                <div style="display:flex; flex-wrap:wrap; gap:6px; margin-bottom:14px;">
                    <?php foreach ( $urls['ig'] as $label => $url ) : ?>
                        <a href="<?php echo esc_url( $url ); ?>" target="_blank" rel="noopener"
                           class="button button-secondary button-small">
                            <?php echo esc_html( $label ); ?> ↗
                        </a>
                    <?php endforeach; ?>
                    <?php if ( empty( $urls['ig'] ) ) : ?>
                        <span class="description"><?php esc_html_e( 'IGアカウントまたはハッシュタグを設定してください。', 'kuchikomi-wall' ); ?></span>
                    <?php endif; ?>
                </div>

                <p style="margin:0 0 6px; font-weight:600;">Facebook</p>
                <div style="display:flex; flex-wrap:wrap; gap:6px;">
                    <?php foreach ( $urls['fb'] as $label => $url ) : ?>
                        <a href="<?php echo esc_url( $url ); ?>" target="_blank" rel="noopener"
                           class="button button-secondary button-small">
                            <?php echo esc_html( $label ); ?> ↗
                        </a>
                    <?php endforeach; ?>
                    <?php if ( empty( $urls['fb'] ) ) : ?>
                        <span class="description"><?php esc_html_e( 'Facebook URLを設定してください。', 'kuchikomi-wall' ); ?></span>
                    <?php endif; ?>
                </div>

            </div>
        </div>
        <?php
    }

    // =========================================
    // セクション③：口コミを登録
    // =========================================

    private function render_add_section() {
        ?>
        <div class="postbox" style="height:fit-content;">
            <h2 class="hndle" style="padding:12px 16px; font-size:14px;">
                <?php esc_html_e( '③ 口コミを登録', 'kuchikomi-wall' ); ?>
            </h2>
            <div class="inside">

                <p style="margin:0 0 8px;">
                    <strong><?php esc_html_e( '投稿URLを貼り付け（Xのみ自動取得）', 'kuchikomi-wall' ); ?></strong>
                </p>
                <div style="display:flex; gap:6px; margin-bottom:12px;">
                    <input type="url" id="tmnl_fetch_url" class="large-text"
                           placeholder="https://x.com/username/status/..." style="flex:1;">
                    <button type="button" id="tmnl_fetch_btn" class="button button-secondary">
                        <?php esc_html_e( '読み込む', 'kuchikomi-wall' ); ?>
                    </button>
                </div>
                <div id="tmnl_fetch_msg" style="margin-bottom:8px; font-size:12px;"></div>

                <form method="post">
                    <?php wp_nonce_field( 'tmnl_add_collected' ); ?>
                    <input type="hidden" name="tmnl_sns_action" value="add_collected">

                    <table class="form-table" style="margin:0;">
                        <tr>
                            <th style="width:80px; padding:6px 10px;"><label for="col_author"><?php esc_html_e( '投稿者', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:6px 10px;">
                                <input type="text" id="col_author" name="col_author" class="regular-text" required>
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:6px 10px;"><label for="col_text"><?php esc_html_e( '内容', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:6px 10px;">
                                <textarea id="col_text" name="col_text" rows="4" class="large-text" required></textarea>
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:6px 10px;"><label for="col_rating"><?php esc_html_e( '評価', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:6px 10px;">
                                <select id="col_rating" name="col_rating">
                                    <option value="5" selected>★★★★★（5）</option>
                                    <option value="4">★★★★☆（4）</option>
                                    <option value="3">★★★☆☆（3）</option>
                                    <option value="2">★★☆☆☆（2）</option>
                                    <option value="1">★☆☆☆☆（1）</option>
                                    <option value="0"><?php esc_html_e( '非表示', 'kuchikomi-wall' ); ?></option>
                                </select>
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:6px 10px;"><label><?php esc_html_e( 'SNS種別', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:6px 10px;">
                                <label><input type="radio" name="col_sns_type" value="x_collected" checked> X (Twitter)</label>&nbsp;&nbsp;
                                <label><input type="radio" name="col_sns_type" value="ig_collected"> Instagram</label>&nbsp;&nbsp;
                                <label><input type="radio" name="col_sns_type" value="fb_collected"> Facebook</label>
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:6px 10px;"><label><?php esc_html_e( 'タグ', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:6px 10px;">
                                <label><input type="checkbox" name="col_tags[]" value="good"> <?php esc_html_e( '良い口コミ', 'kuchikomi-wall' ); ?></label>&nbsp;
                                <label><input type="checkbox" name="col_tags[]" value="photo"> <?php esc_html_e( '写真付き', 'kuchikomi-wall' ); ?></label>&nbsp;
                                <label><input type="checkbox" name="col_tags[]" value="viral"> <?php esc_html_e( '拡散あり', 'kuchikomi-wall' ); ?></label>
                            </td>
                        </tr>
                        <tr>
                            <th style="padding:6px 10px;"><label for="col_source_url"><?php esc_html_e( '元URL', 'kuchikomi-wall' ); ?></label></th>
                            <td style="padding:6px 10px;">
                                <input type="url" id="col_source_url" name="col_source_url" class="large-text"
                                       placeholder="https://...">
                            </td>
                        </tr>
                    </table>

                    <div style="padding:10px 10px 12px; display:flex; gap:8px;">
                        <button type="submit" name="col_submit" value="pending" class="button button-secondary">
                            <?php esc_html_e( '保留に追加', 'kuchikomi-wall' ); ?>
                        </button>
                        <button type="submit" name="col_submit" value="publish" class="button button-primary">
                            <?php esc_html_e( '今すぐ掲載', 'kuchikomi-wall' ); ?>
                        </button>
                    </div>
                </form>
            </div>
        </div>
        <?php
    }

    // =========================================
    // セクション④：保留キュー
    // =========================================

    private function render_queue_section() {
        $pending = TMNL_DB::get_pending();
        ?>
        <div class="postbox" style="margin-top:20px;">
            <h2 class="hndle" style="padding:12px 16px; font-size:14px;">
                <?php
                printf(
                    esc_html__( '④ 保留キュー（%d件）', 'kuchikomi-wall' ),
                    count( $pending )
                );
                ?>
            </h2>
            <div class="inside" style="padding:0;">
                <?php if ( empty( $pending ) ) : ?>
                    <p style="padding:12px 16px; margin:0; color:#777;">
                        <?php esc_html_e( '保留中の口コミはありません。', 'kuchikomi-wall' ); ?>
                    </p>
                <?php else : ?>
                    <table class="wp-list-table widefat fixed striped" style="margin:0; border:none;">
                        <thead>
                            <tr>
                                <th style="width:130px;"><?php esc_html_e( '投稿者', 'kuchikomi-wall' ); ?></th>
                                <th><?php esc_html_e( '内容', 'kuchikomi-wall' ); ?></th>
                                <th style="width:90px;"><?php esc_html_e( 'SNS', 'kuchikomi-wall' ); ?></th>
                                <th style="width:120px;"><?php esc_html_e( 'タグ', 'kuchikomi-wall' ); ?></th>
                                <th style="width:90px;"><?php esc_html_e( '評価', 'kuchikomi-wall' ); ?></th>
                                <th style="width:90px;"><?php esc_html_e( '登録日', 'kuchikomi-wall' ); ?></th>
                                <th style="width:130px;"><?php esc_html_e( '操作', 'kuchikomi-wall' ); ?></th>
                            </tr>
                        </thead>
                        <tbody>
                        <?php foreach ( $pending as $row ) :
                            $sns_label = $this->sns_type_label( $row->source_type );
                            $tags      = $row->sns_tags ? implode( ', ', array_map( array( $this, 'tag_label' ), explode( ',', $row->sns_tags ) ) ) : '—';
                            $rating    = intval( $row->rating );
                            $stars     = $rating > 0 ? str_repeat( '★', $rating ) . str_repeat( '☆', 5 - $rating ) : esc_html__( '非表示', 'kuchikomi-wall' );
                        ?>
                            <tr>
                                <td>
                                    <?php echo esc_html( $row->author_name ); ?>
                                    <?php if ( ! empty( $row->source_url ) ) : ?>
                                        <br><a href="<?php echo esc_url( $row->source_url ); ?>" target="_blank" style="font-size:11px;">元投稿 ↗</a>
                                    <?php endif; ?>
                                </td>
                                <td style="word-break:break-all;"><?php echo esc_html( mb_substr( $row->text, 0, 80 ) . ( mb_strlen( $row->text ) > 80 ? '…' : '' ) ); ?></td>
                                <td><?php echo esc_html( $sns_label ); ?></td>
                                <td style="font-size:12px;"><?php echo esc_html( $tags ); ?></td>
                                <td style="font-size:12px;"><?php echo esc_html( $stars ); ?></td>
                                <td><?php echo esc_html( substr( $row->created_at, 0, 10 ) ); ?></td>
                                <td>
                                    <a href="<?php echo wp_nonce_url(
                                        add_query_arg( array( 'page' => 'tmnl-sns-collect', 'tmnl_col_action' => 'publish', 'col_id' => $row->id ), admin_url( 'admin.php' ) ),
                                        'tmnl_col_publish_' . $row->id, '_tmnl_nonce'
                                    ); ?>" class="button button-primary button-small"><?php esc_html_e( '掲載', 'kuchikomi-wall' ); ?></a>
                                    <a href="<?php echo wp_nonce_url(
                                        add_query_arg( array( 'page' => 'tmnl-sns-collect', 'tmnl_col_action' => 'delete', 'col_id' => $row->id ), admin_url( 'admin.php' ) ),
                                        'tmnl_col_delete_' . $row->id, '_tmnl_nonce'
                                    ); ?>" class="button button-small"
                                       onclick="return confirm('<?php echo esc_js( __( '削除してよいですか？', 'kuchikomi-wall' ) ); ?>')"
                                       style="color:#a00; border-color:#a00;"><?php esc_html_e( '削除', 'kuchikomi-wall' ); ?></a>
                                </td>
                            </tr>
                        <?php endforeach; ?>
                        </tbody>
                    </table>
                <?php endif; ?>
            </div>
        </div>
        <?php
    }

    // =========================================
    // アップグレード案内（Free版）
    // =========================================

    private function render_upgrade_notice() {
        $upgrade_url = function_exists( 'kw_fs' ) ? kw_fs()->get_upgrade_url() : '#';
        ?>
        <div class="wrap">
            <h1><?php esc_html_e( '口コミ収集', 'kuchikomi-wall' ); ?></h1>
            <div style="margin-top:20px; padding:24px 28px; background:#fff; border:1px solid #ddd; border-left:4px solid #2271b1; max-width:600px;">
                <h2 style="margin:0 0 10px; font-size:16px;">
                    <?php esc_html_e( 'この機能はPro版でご利用いただけます', 'kuchikomi-wall' ); ?>
                </h2>
                <p style="margin:0 0 16px; color:#555;">
                    <?php esc_html_e( 'X (Twitter)・Instagram・Facebook から口コミを簡単に収集・管理できます。URLを貼るだけで投稿内容を自動取得し、保留キューで確認してから掲載できます。', 'kuchikomi-wall' ); ?>
                </p>
                <a href="<?php echo esc_url( $upgrade_url ); ?>" class="button button-primary">
                    <?php esc_html_e( 'Pro にアップグレード', 'kuchikomi-wall' ); ?>
                </a>
            </div>
        </div>
        <?php
    }

    // =========================================
    // 通知バー
    // =========================================

    private function render_notices() {
        if ( isset( $_GET['saved'] ) )     : ?><div class="notice notice-success is-dismissible"><p><?php esc_html_e( '設定を保存しました。', 'kuchikomi-wall' ); ?></p></div><?php endif;
        if ( isset( $_GET['added'] ) )     : ?><div class="notice notice-success is-dismissible"><p><?php esc_html_e( '口コミを追加しました。', 'kuchikomi-wall' ); ?></p></div><?php endif;
        if ( isset( $_GET['published'] ) ) : ?><div class="notice notice-success is-dismissible"><p><?php esc_html_e( '掲載しました。', 'kuchikomi-wall' ); ?></p></div><?php endif;
        if ( isset( $_GET['deleted'] ) )   : ?><div class="notice notice-success is-dismissible"><p><?php esc_html_e( '削除しました。', 'kuchikomi-wall' ); ?></p></div><?php endif;
    }

    // =========================================
    // JS（AJAX + フォーム連携）
    // =========================================

    private function render_js() {
        ?>
        <script>
        (function() {
            var fetchBtn = document.getElementById('tmnl_fetch_btn');
            var fetchUrl = document.getElementById('tmnl_fetch_url');
            var fetchMsg = document.getElementById('tmnl_fetch_msg');

            if ( ! fetchBtn ) return;

            fetchBtn.addEventListener('click', function() {
                var url = fetchUrl.value.trim();
                if ( ! url ) {
                    fetchMsg.style.color = '#c00';
                    fetchMsg.textContent = 'URLを入力してください。';
                    return;
                }

                // Xのみ自動取得
                if ( ! /x\.com|twitter\.com/.test( url ) ) {
                    // X以外：URLだけ元URLに自動入力
                    document.getElementById('col_source_url').value = url;
                    fetchMsg.style.color = '#777';
                    fetchMsg.textContent = 'X以外のSNSは手動で入力してください。元URLに自動入力しました。';
                    return;
                }

                fetchBtn.disabled = true;
                fetchMsg.style.color = '#777';
                fetchMsg.textContent = '取得中...';

                var data = new FormData();
                data.append('action', 'tmnl_fetch_x_url');
                data.append('nonce', '<?php echo wp_create_nonce( 'tmnl_fetch_x' ); ?>');
                data.append('url', url);

                fetch(ajaxurl, { method: 'POST', body: data })
                    .then(function(r) { return r.json(); })
                    .then(function(res) {
                        fetchBtn.disabled = false;
                        if ( res.success ) {
                            document.getElementById('col_author').value     = res.data.author_name || '';
                            document.getElementById('col_text').value       = res.data.text        || '';
                            document.getElementById('col_source_url').value = res.data.source_url  || '';
                            fetchMsg.style.color = '#080';
                            fetchMsg.textContent = '取得しました。内容を確認してから登録してください。';
                        } else {
                            fetchMsg.style.color = '#c00';
                            fetchMsg.textContent = res.data.message || '取得に失敗しました。';
                        }
                    })
                    .catch(function() {
                        fetchBtn.disabled = false;
                        fetchMsg.style.color = '#c00';
                        fetchMsg.textContent = '通信エラーが発生しました。';
                    });
            });
        })();
        </script>
        <?php
    }

    // =========================================
    // データ保存・生成ヘルパー
    // =========================================

    private function save_accounts() {
        $data = array(
            'x_account'   => sanitize_text_field( $_POST['x_account'] ?? '' ),
            'store_names' => array_filter( array_map( 'sanitize_text_field', explode( "\n", $_POST['store_names'] ?? '' ) ) ),
            'ig_account'  => sanitize_text_field( $_POST['ig_account'] ?? '' ),
            'ig_hashtags' => array_filter( array_map( 'sanitize_text_field', explode( "\n", $_POST['ig_hashtags'] ?? '' ) ) ),
            'fb_url'      => esc_url_raw( $_POST['fb_url'] ?? '' ),
        );
        update_option( $this->option_key, $data );
    }

    private function add_collected( $post ) {
        $submit     = sanitize_key( $post['col_submit'] ?? 'pending' );
        $is_pending = ( $submit === 'pending' );
        $sns_type   = sanitize_key( $post['col_sns_type'] ?? 'x_collected' );

        $sns_labels = array(
            'x_collected'  => 'X (Twitter)',
            'ig_collected' => 'Instagram',
            'fb_collected' => 'Facebook',
        );

        $tags     = array_map( 'sanitize_key', (array) ( $post['col_tags'] ?? array() ) );
        $tags_str = implode( ',', $tags );

        TMNL_DB::insert( array(
            'author_name'  => sanitize_text_field( $post['col_author'] ?? '' ),
            'rating'       => intval( $post['col_rating'] ?? 5 ),
            'text'         => sanitize_textarea_field( $post['col_text'] ?? '' ),
            'review_date'  => current_time( 'Y-m-d' ),
            'source_label' => $sns_labels[ $sns_type ] ?? 'SNS',
            'source_type'  => $sns_type,
            'is_visible'   => $is_pending ? 0 : 1,
            'status'       => $is_pending ? 'pending' : 'published',
            'source_url'   => esc_url_raw( $post['col_source_url'] ?? '' ) ?: null,
            'sns_tags'     => $tags_str ?: null,
        ) );
    }

    private function get_accounts() {
        return (array) get_option( $this->option_key, array() );
    }

    private function build_search_urls( $accounts ) {
        $x_account   = ltrim( $accounts['x_account'] ?? '', '@' );
        $store_names = $accounts['store_names'] ?? array();
        $ig_account  = ltrim( $accounts['ig_account'] ?? '', '@' );
        $ig_hashtags = $accounts['ig_hashtags'] ?? array();
        $fb_url      = $accounts['fb_url'] ?? '';

        $urls = array( 'x' => array(), 'ig' => array(), 'fb' => array() );

        // X
        if ( $x_account ) {
            $urls['x'][ '@メンション検索' ] = 'https://x.com/search?q=' . rawurlencode( '@' . $x_account ) . '&f=live';
        }
        if ( ! empty( $store_names ) ) {
            $first = reset( $store_names );
            $urls['x']['店名検索'] = 'https://x.com/search?q=' . rawurlencode( $first ) . '&f=live';
            if ( $x_account && count( $store_names ) > 0 ) {
                $or_query = implode( ' OR ', $store_names ) . ( $x_account ? ' OR @' . $x_account : '' );
                $urls['x']['複合検索'] = 'https://x.com/search?q=' . rawurlencode( $or_query ) . '&f=live';
            }
        }

        // Instagram
        if ( $ig_account ) {
            $urls['ig']['タグ付け投稿'] = 'https://www.instagram.com/' . rawurlencode( $ig_account ) . '/tagged/';
        }
        foreach ( $ig_hashtags as $tag ) {
            $clean = ltrim( trim( $tag ), '#' );
            if ( $clean ) {
                $urls['ig'][ '#' . $clean ] = 'https://www.instagram.com/explore/tags/' . rawurlencode( $clean ) . '/';
            }
        }

        // Facebook
        if ( $fb_url ) {
            $urls['fb']['店舗ページ'] = $fb_url;
        }
        if ( ! empty( $store_names ) ) {
            $first = reset( $store_names );
            $urls['fb']['検索'] = 'https://www.facebook.com/search/top?q=' . rawurlencode( $first );
        }

        return $urls;
    }

    private function sns_type_label( $type ) {
        $map = array(
            'x_collected'  => 'X',
            'ig_collected' => 'IG',
            'fb_collected' => 'FB',
        );
        return $map[ $type ] ?? $type;
    }

    private function tag_label( $tag ) {
        $map = array(
            'good'  => '良い口コミ',
            'photo' => '写真付き',
            'viral' => '拡散あり',
        );
        return $map[ trim( $tag ) ] ?? $tag;
    }
}
