<?php

if ( ! defined( 'ABSPATH' ) ) exit;



/**

 * AI プロバイダ / 画像プロバイダ / 画像設定タブのレンダリング

 *

 * 元 admin/class-aiap-admin-view.php から分離。

 * 共通基盤 (meta_label, resolve_dynamic_key) は親クラス AIAP_Admin_View にあるため直接参照する。

 */

class AIAP_Admin_View_Provider {



    // ================================================================

    // AIプロバイダ — サブタブ方式 (BotWriter style)

    // ================================================================

    public static function render_provider( $s ) {

        $sub = sanitize_key( wp_unslash( $_GET['sub'] ?? ( $s['provider'] ?? 'claude' ) ) );

        if ( ! isset( AIAP_Admin::$prov_icons[ $sub ] ) ) $sub = 'claude';

        // 各プロバイダのモデル一覧（キャッシュがあればそれを、なければハードコードのデフォルト）

        $models = array();

        $discontinued = array();

        foreach ( array_keys( AIAP_Admin::$prov_icons ) as $pkey ) {

            $list = AIAP_AI_Providers::get_models_for( $pkey );

            $models[ $pkey ] = $list;

            $mfield = $pkey . '_model';

            $cur = $s[ $mfield ] ?? '';

            if ( $cur !== '' && ! empty( $list ) && ! isset( $list[ $cur ] ) ) {

                $discontinued[ $pkey ] = $cur;

            }

        }

        $key_map   = array();
        $model_map = array();
        foreach ( array_keys( AIAP_Admin::$prov_icons ) as $pkey ) {
            $key_map[ $pkey ]   = AIAP_AI_Providers::get_key_field( $pkey );
            $model_map[ $pkey ] = AIAP_AI_Providers::get_model_field( $pkey );
        }
        // よく使われる3プロバイダを上に、残りを下にコンパクト表示

        $popular = array( 'openai', 'claude', 'gemini' );

        $others  = array_values( array_diff( array_keys( AIAP_Admin::$prov_icons ), $popular ) );

        $active_provider = isset( $s['provider'] ) && isset( AIAP_Admin::$prov_icons[ $s['provider'] ] ) ? $s['provider'] : 'claude';

        ?>

        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="aiap-provider-form">

        <input type="hidden" name="action" value="aiap_save_provider">

        <input type="hidden" id="aiap-provider-tab" name="provider_tab" value="<?php echo esc_attr( $active_provider ); ?>">

        <input type="hidden" name="provider" id="aiap-active-provider-input" value="<?php echo esc_attr( $active_provider ); ?>">

        <?php wp_nonce_field( AIAP_Admin::NONCE ); ?>



        <header class="aiap-provider-hero">

            <span class="aiap-provider-hero-eyebrow"><?php echo esc_html( __( 'AI Provider', 'ai-auto-poster' ) ); ?></span>

            <h2 class="aiap-provider-hero-title"><?php echo esc_html( __( 'Which AI will write your articles?', 'ai-auto-poster' ) ); ?></h2>

            <p class="aiap-provider-hero-sub"><?php echo esc_html( __( 'Pick one, and it will be used for auto-posting. You can change it later.', 'ai-auto-poster' ) ); ?></p>

        </header>



        <div class="aiap-provider-section-label"><?php echo esc_html( __( 'Most common', 'ai-auto-poster' ) ); ?></div>

        <div class="aiap-provider-popular" id="aiap-providers-popular" role="radiogroup" aria-label="<?php echo esc_attr( __( 'Popular AI providers', 'ai-auto-poster' ) ); ?>">

            <?php

            $not_set_label   = __( 'Not set', 'ai-auto-poster' );

            $configured_label = __( 'Configured', 'ai-auto-poster' );

            foreach ( $popular as $pkey ) :

                $pi          = AIAP_Admin::$prov_icons[ $pkey ];

                $name        = AIAP_Admin_View::meta_label( $pi );

                $sub_text    = self::provider_subtitle( $pkey );

                $is_active   = ( $active_provider === $pkey );

                $is_configured = ! empty( $s[ $key_map[ $pkey ] ] );

                ?>

                <button type="button"

                    class="aiap-provider-tile<?php echo $is_active ? ' is-selected' : ''; ?>"

                    data-aiap-provider="<?php echo esc_attr( $pkey ); ?>"

                    data-aiap-name="<?php echo esc_attr( $name ); ?>"

                    data-aiap-sub="<?php echo esc_attr( $sub_text ); ?>"

                    data-aiap-icon-class="<?php echo esc_attr( $pi['ico'] ); ?>"

                    data-aiap-letter="<?php echo esc_attr( $pi['letter'] ); ?>"

                    role="radio"

                    aria-checked="<?php echo $is_active ? 'true' : 'false'; ?>">

                    <span class="aiap-provider-tile-icon ico ico-lg <?php echo esc_attr( $pi['ico'] ); ?>" aria-hidden="true"><?php echo esc_html( $pi['letter'] ); ?></span>

                    <span class="aiap-provider-tile-meta">

                        <span class="aiap-provider-tile-name"><?php echo esc_html( $name ); ?></span>

                        <?php if ( $sub_text !== '' ) : ?>

                            <span class="aiap-provider-tile-sub"><?php echo esc_html( $sub_text ); ?></span>

                        <?php endif; ?>

                    </span>

                    <span class="aiap-provider-tile-status<?php echo $is_configured ? ' is-configured' : ' is-empty'; ?>">

                        <?php echo esc_html( $is_configured ? $configured_label : $not_set_label ); ?>

                    </span>

                    <span class="aiap-provider-tile-check" aria-hidden="true">

                        <svg viewBox="0 0 24 24" width="13" height="13" focusable="false"><path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>

                    </span>

                </button>

            <?php endforeach; ?>

        </div>



        <div class="aiap-provider-section-label"><?php echo esc_html( __( 'Other providers', 'ai-auto-poster' ) ); ?></div>

        <div class="aiap-provider-other" role="radiogroup" aria-label="<?php echo esc_attr( __( 'Other AI providers', 'ai-auto-poster' ) ); ?>">

            <?php foreach ( $others as $pkey ) :

                $pi          = AIAP_Admin::$prov_icons[ $pkey ];

                $name        = AIAP_Admin_View::meta_label( $pi );

                $sub_text    = self::provider_subtitle( $pkey );

                $is_active   = ( $active_provider === $pkey );

                $is_configured = ! empty( $s[ $key_map[ $pkey ] ] );

                ?>

                <button type="button"

                    class="aiap-provider-tile-compact<?php echo $is_active ? ' is-selected' : ''; ?>"

                    data-aiap-provider="<?php echo esc_attr( $pkey ); ?>"

                    data-aiap-name="<?php echo esc_attr( $name ); ?>"

                    data-aiap-sub="<?php echo esc_attr( $sub_text ); ?>"

                    data-aiap-icon-class="<?php echo esc_attr( $pi['ico'] ); ?>"

                    data-aiap-letter="<?php echo esc_attr( $pi['letter'] ); ?>"

                    role="radio"

                    aria-checked="<?php echo $is_active ? 'true' : 'false'; ?>">

                    <span class="aiap-provider-tile-icon ico <?php echo esc_attr( $pi['ico'] ); ?>" aria-hidden="true"><?php echo esc_html( $pi['letter'] ); ?></span>

                    <span class="aiap-provider-tile-name"><?php echo esc_html( $name ); ?></span>

                    <span class="aiap-provider-tile-status<?php echo $is_configured ? ' is-configured' : ' is-empty'; ?>" aria-label="<?php echo esc_attr( $is_configured ? $configured_label : $not_set_label ); ?>"></span>

                    <span class="aiap-provider-tile-check" aria-hidden="true">

                        <svg viewBox="0 0 24 24" width="11" height="11" focusable="false"><path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>

                    </span>

                </button>

            <?php endforeach; ?>

        </div>



        <?php // 各プロバイダの設定パネル (active のみ表示)。フォーム項目はすべて DOM に存在するので保存ハンドラは無変更で動く。 ?>

        <?php foreach ( AIAP_Admin::$prov_icons as $card_key => $pi ) :

            $is_active = ( $active_provider === $card_key );

            $key_field = $key_map[ $card_key ];

            $has_key   = ! empty( $s[ $key_field ] );

            $name      = AIAP_Admin_View::meta_label( $pi );

            $sub_text  = self::provider_subtitle( $card_key );

            ?>

            <div class="aiap-provider-panel aiap-card aiap-provider-card aiap-text-provider-card" id="aiap-provider-card-<?php echo esc_attr( $card_key ); ?>" data-aiap-panel-for="<?php echo esc_attr( $card_key ); ?>" <?php echo $is_active ? '' : 'hidden'; ?>>

                <header class="aiap-provider-panel-header">

                    <span class="aiap-provider-panel-icon ico ico-lg <?php echo esc_attr( $pi['ico'] ); ?>" aria-hidden="true"><?php echo esc_html( $pi['letter'] ); ?></span>

                    <span class="aiap-provider-panel-text">

                        <span class="aiap-provider-panel-title"><?php echo esc_html( $name ); ?></span>

                        <?php if ( $sub_text !== '' ) : ?>

                            <span class="aiap-provider-panel-sub"><?php echo esc_html( $sub_text ); ?></span>

                        <?php endif; ?>

                    </span>

                    <span class="aiap-provider-panel-active"><?php echo esc_html( __( 'In use', 'ai-auto-poster' ) ); ?></span>

                </header>

                <div class="aiap-provider-panel-body">

                    <div class="aiap-field">

                        <label class="aiap-field-label" for="aiap-apikey-<?php echo esc_attr( $card_key ); ?>"><?php echo esc_html( __( 'API Key', 'ai-auto-poster' ) ); ?></label>

                        <div class="aiap-field-row">

                            <?php
                            // $s は AIAP_AI_Client::get_settings() → get_decrypted() 経由で
                            // すでに復号済みの平文 API キーを保持している。再復号は不要。
                            AIAP_Admin_View::render_password_field( 'aiap-apikey-' . $card_key, $key_field, (string) ( $s[ $key_field ] ?? '' ) );
                            ?>

                            <button type="button" class="aiap-btn aiap-btn-primary aiap-btn-test" data-test-kind="text" data-provider="<?php echo esc_attr( $card_key ); ?>">

                                <span class="dashicons dashicons-search"></span> <?php echo esc_html( __( 'Test', 'ai-auto-poster' ) ); ?>

                            </button>

                        </div>

                        <div class="aiap-field-actions">

                            <a href="<?php echo esc_url( AIAP_Admin::$prov_urls[ $card_key ] ); ?>" target="_blank" rel="noopener" class="aiap-field-link">

                                <?php echo esc_html( __( 'Get an API key', 'ai-auto-poster' ) ); ?>

                                <svg viewBox="0 0 24 24" width="11" height="11" fill="none" aria-hidden="true"><path d="M7 17L17 7M17 7H9M17 7v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>

                            </a>

                        </div>

                    </div>



                    <div class="aiap-field">

                        <label class="aiap-field-label" for="aiap-model-<?php echo esc_attr( $card_key ); ?>"><?php echo esc_html( __( 'Model', 'ai-auto-poster' ) ); ?></label>

                        <div class="aiap-field-row">

                            <select id="aiap-model-<?php echo esc_attr( $card_key ); ?>" name="<?php echo esc_attr( $model_map[ $card_key ] ); ?>" class="aiap-select aiap-model-select" data-provider="<?php echo esc_attr( $card_key ); ?>">

                                <?php

                                $model_options = $models[ $card_key ] ?? array();

                                $custom_label  = __( '(custom)', 'ai-auto-poster' );

                                if ( ! empty( $s[ $model_map[ $card_key ] ] ) && ! isset( $model_options[ $s[ $model_map[ $card_key ] ] ] ) ) {

                                    $model_options = array( $s[ $model_map[ $card_key ] ] => $s[ $model_map[ $card_key ] ] . ' ' . $custom_label ) + $model_options;

                                }

                                foreach ( $model_options as $v => $l ) : ?>

                                    <option value="<?php echo esc_attr( $v ); ?>" <?php selected( $s[ $model_map[ $card_key ] ], $v ); ?>><?php echo esc_html( $l ); ?></option>

                                <?php endforeach; ?>

                            </select>

                            <button type="button" class="aiap-btn aiap-btn-icon aiap-btn-refresh-models" data-provider="<?php echo esc_attr( $card_key ); ?>" title="<?php echo esc_attr( __( 'Refresh model list', 'ai-auto-poster' ) ); ?>" aria-label="<?php echo esc_attr( __( 'Refresh model list', 'ai-auto-poster' ) ); ?>">

                                <span class="dashicons dashicons-update" aria-hidden="true"></span>

                            </button>

                        </div>

                        <?php if ( isset( $discontinued[ $card_key ] ) ) : ?>

                            <p class="aiap-model-notice"><span class="dashicons dashicons-warning" aria-hidden="true"></span> <?php

                                /* translators: %s = model identifier (e.g. "gpt-4-turbo") that has been discontinued */

                                echo esc_html( sprintf( __( 'Selected model "%s" is no longer available. It will be switched on save.', 'ai-auto-poster' ), $discontinued[ $card_key ] ) );

                            ?></p>

                        <?php endif; ?>

                        <p class="aiap-model-feedback" data-provider="<?php echo esc_attr( $card_key ); ?>" hidden></p>

                    </div>



                    <div class="aiap-field">

                        <label class="aiap-field-label" for="aiap-custom-model-<?php echo esc_attr( $card_key ); ?>">

                            <?php echo esc_html( __( 'Custom model', 'ai-auto-poster' ) ); ?>

                            <span class="aiap-field-label-hint"><?php echo esc_html( __( 'optional', 'ai-auto-poster' ) ); ?></span>

                        </label>

                        <input type="text" id="aiap-custom-model-<?php echo esc_attr( $card_key ); ?>" class="aiap-input-text" name="<?php echo esc_attr( $card_key ); ?>_custom_model" data-aiap-custom-model placeholder="<?php echo esc_attr( __( 'Enter a model ID not in the list', 'ai-auto-poster' ) ); ?>">

                    </div>

                </div>

            </div>

        <?php endforeach; ?>



        <p class="submit aiap-provider-submit"><button type="submit" class="button button-primary aiap-btn-primary"><span class="dashicons dashicons-saved"></span> <?php echo esc_html( __( 'Save', 'ai-auto-poster' ) ); ?></button></p>

        </form>

        <?php

    }



    /**

     * プロバイダのサブタイトル (タイル/パネルに表示)。

     */

    private static function provider_subtitle( $key ) {

        switch ( $key ) {

            case 'openai':     return __( 'ChatGPT API', 'ai-auto-poster' );

            case 'claude':     return __( 'Anthropic', 'ai-auto-poster' );

            case 'gemini':     return __( 'Google AI Studio', 'ai-auto-poster' );

            case 'mistral':    return __( 'Mistral AI', 'ai-auto-poster' );

            case 'groq':       return __( 'Groq Cloud', 'ai-auto-poster' );

            case 'deepseek':   return __( 'DeepSeek', 'ai-auto-poster' );

            case 'openrouter': return __( 'OpenRouter', 'ai-auto-poster' );

        }

        return '';

    }



    // ================================================================

    // 画像AIプロバイダ — サブタブ方式 (BotWriter style)

    // ================================================================

    public static function render_image_provider( $s, $im ) {

        $sub = sanitize_key( wp_unslash( $_GET['sub'] ?? ( $im['image_source'] ?? 'dalle3' ) ) );

        if ( ! isset( AIAP_Admin::$img_icons[ $sub ] ) ) $sub = 'dalle3';

        // UI 表示用メタ (URL / モデル名フィールド / モデル一覧)。

        // 'key' カラムは AIAP_Admin::$image_provider_key_field を単一情報源として参照する

        // (CLAUDE.md 重複排除: 旧実装はここでも同じ値をハードコードしていた)。

        $img_url_map = array(

            'dalle3'    => array( 'model'=>null, 'url'=>'https://platform.openai.com/api-keys' ),

            'imagen'    => array( 'model'=>null, 'url'=>'https://aistudio.google.com/app/apikey' ),

            'stability' => array( 'model'=>'stability_model', 'url'=>'https://platform.stability.ai/', 'models'=>AIAP_Model_Registry::image_model_ids( 'stability' ) ),

            'flux'      => array( 'model'=>'flux_model',      'url'=>'https://fal.ai/dashboard/keys', 'models'=>AIAP_Model_Registry::image_model_ids( 'flux' ) ),

            'unsplash'  => array( 'model'=>null, 'url'=>'https://unsplash.com/developers' ),

            'pixabay'   => array( 'model'=>null, 'url'=>'https://pixabay.com/api/docs/' ),

            'pexels'    => array( 'model'=>null, 'url'=>'https://www.pexels.com/api/' ),

        );

        $img_keys = array();

        foreach ( $img_url_map as $pkey => $meta ) {

            $img_keys[ $pkey ] = array_merge(

                array( 'key' => AIAP_Image_Client::get_key_field( $pkey ) ),
                $meta

            );

        }

        $notes = array( 'openverse'=>'openverse_desc' );



        $dynamic_providers = array( 'dalle3', 'imagen' );

        $img_models = array();

        $img_discontinued = array();

        foreach ( $dynamic_providers as $pkey ) {

            $list = AIAP_AI_Providers::get_models_for( $pkey );

            $img_models[ $pkey ] = $list;

            $mfield = $pkey . '_model';

            $cur = $im[ $mfield ] ?? '';

            if ( $cur !== '' && ! empty( $list ) && ! isset( $list[ $cur ] ) ) {

                $img_discontinued[ $pkey ] = $cur;

            }

        }



        // よく使われる4 (AI生成2 + 写真素材2)、その他

        $popular = array( 'dalle3', 'imagen', 'unsplash', 'pexels' );

        $others  = array_values( array_diff( array_keys( AIAP_Admin::$img_icons ), $popular ) );

        $active = isset( $im['image_source'] ) && isset( AIAP_Admin::$img_icons[ $im['image_source'] ] ) ? $im['image_source'] : 'dalle3';

        $not_set_label    = __( 'Not set', 'ai-auto-poster' );

        $configured_label = __( 'Configured', 'ai-auto-poster' );

        ?>

        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="aiap-provider-form">

        <input type="hidden" name="action" value="aiap_save_image_provider">

        <input type="hidden" id="aiap-image-tab" name="image_tab" value="<?php echo esc_attr( $active ); ?>">

        <input type="hidden" name="image_source" id="aiap-active-image-source-input" value="<?php echo esc_attr( $active ); ?>">

        <?php wp_nonce_field( AIAP_Admin::NONCE ); ?>



        <header class="aiap-provider-hero">

            <span class="aiap-provider-hero-eyebrow"><?php echo esc_html( __( 'Featured Image', 'ai-auto-poster' ) ); ?></span>

            <h2 class="aiap-provider-hero-title"><?php echo esc_html( __( 'Where do your images come from?', 'ai-auto-poster' ) ); ?></h2>

            <p class="aiap-provider-hero-sub"><?php echo esc_html( __( 'Choose an AI image generator or a stock photo source. You can change it anytime.', 'ai-auto-poster' ) ); ?></p>

        </header>



        <div class="aiap-provider-section-label"><?php echo esc_html( __( 'Most common', 'ai-auto-poster' ) ); ?></div>

        <div class="aiap-provider-popular" id="aiap-image-providers-popular" role="radiogroup" aria-label="<?php echo esc_attr( __( 'Popular image sources', 'ai-auto-poster' ) ); ?>">

            <?php foreach ( $popular as $pkey ) :

                if ( ! isset( AIAP_Admin::$img_icons[ $pkey ] ) ) continue;

                $ii = AIAP_Admin::$img_icons[ $pkey ];

                $name = AIAP_Admin_View::meta_label( $ii );

                $sub_text = self::image_provider_subtitle( $pkey );

                $is_active = ( $active === $pkey );

                $is_configured = AIAP_Image_Client::has_required_credentials( $pkey, $im );
                ?>

                <button type="button"

                    class="aiap-provider-tile<?php echo $is_active ? ' is-selected' : ''; ?>"

                    data-aiap-image-source="<?php echo esc_attr( $pkey ); ?>"

                    role="radio"

                    aria-checked="<?php echo $is_active ? 'true' : 'false'; ?>">

                    <span class="aiap-provider-tile-icon ico ico-lg <?php echo esc_attr( $ii['ico'] ); ?>" aria-hidden="true"><?php echo esc_html( $ii['letter'] ); ?></span>

                    <span class="aiap-provider-tile-meta">

                        <span class="aiap-provider-tile-name"><?php echo esc_html( $name ); ?></span>

                        <?php if ( $sub_text !== '' ) : ?>

                            <span class="aiap-provider-tile-sub"><?php echo esc_html( $sub_text ); ?></span>

                        <?php endif; ?>

                    </span>

                    <span class="aiap-provider-tile-status<?php echo $is_configured ? ' is-configured' : ' is-empty'; ?>">

                        <?php echo esc_html( $is_configured ? $configured_label : $not_set_label ); ?>

                    </span>

                    <span class="aiap-provider-tile-check" aria-hidden="true">

                        <svg viewBox="0 0 24 24" width="13" height="13" focusable="false"><path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>

                    </span>

                </button>

            <?php endforeach; ?>

        </div>



        <div class="aiap-provider-section-label"><?php echo esc_html( __( 'Other sources', 'ai-auto-poster' ) ); ?></div>

        <div class="aiap-provider-other" role="radiogroup" aria-label="<?php echo esc_attr( __( 'Other image sources', 'ai-auto-poster' ) ); ?>">

            <?php foreach ( $others as $pkey ) :

                $ii = AIAP_Admin::$img_icons[ $pkey ];

                $name = AIAP_Admin_View::meta_label( $ii );

                $is_active = ( $active === $pkey );

                $is_configured = AIAP_Image_Client::has_required_credentials( $pkey, $im );
                ?>

                <button type="button"

                    class="aiap-provider-tile-compact<?php echo $is_active ? ' is-selected' : ''; ?>"

                    data-aiap-image-source="<?php echo esc_attr( $pkey ); ?>"

                    role="radio"

                    aria-checked="<?php echo $is_active ? 'true' : 'false'; ?>">

                    <span class="aiap-provider-tile-icon ico <?php echo esc_attr( $ii['ico'] ); ?>" aria-hidden="true"><?php echo esc_html( $ii['letter'] ); ?></span>

                    <span class="aiap-provider-tile-name"><?php echo esc_html( $name ); ?></span>

                    <span class="aiap-provider-tile-status<?php echo $is_configured ? ' is-configured' : ' is-empty'; ?>" aria-label="<?php echo esc_attr( $is_configured ? $configured_label : $not_set_label ); ?>"></span>

                    <span class="aiap-provider-tile-check" aria-hidden="true">

                        <svg viewBox="0 0 24 24" width="11" height="11" focusable="false"><path d="M5 12l5 5L20 7" fill="none" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>

                    </span>

                </button>

            <?php endforeach; ?>

        </div>



        <?php foreach ( AIAP_Admin::$img_icons as $card_key => $ii ) :

            $is_active = ( $active === $card_key );

            $name = AIAP_Admin_View::meta_label( $ii );

            $sub_text = self::image_provider_subtitle( $card_key );

            $ik = $img_keys[ $card_key ] ?? null;

            $img_has_key = $ik && ! empty( $im[ $ik['key'] ] );



            // スタイル選択

            $style_key = $card_key . '_style';

            $saved_style = $im[ $style_key ] ?? '';

            $current_model = '';

            if ( in_array( $card_key, $dynamic_providers, true ) ) {

                $current_model = $im[ $card_key . '_model' ] ?? '';

            }

            if ( $current_model === '' && $ik && ! empty( $ik['model'] ) ) {
                $current_model = $im[ $ik['model'] ] ?? '';
            }

            $style_opts = AIAP_Image_Styles::get_provider_styles( $card_key, $current_model );
            $style_has_opts = ! empty( $style_opts );

            $style_unsupported = ( $saved_style !== '' && $style_has_opts && ! isset( $style_opts[ $saved_style ] ) ) ? $saved_style : '';

            $cur_style = ( $style_has_opts && isset( $style_opts[ $saved_style ] ) ) ? $saved_style : ( $style_has_opts ? array_key_first( $style_opts ) : '' );

            ?>

            <div class="aiap-provider-panel aiap-card aiap-provider-card aiap-image-provider-card" id="aiap-image-card-<?php echo esc_attr( $card_key ); ?>" data-aiap-image-panel-for="<?php echo esc_attr( $card_key ); ?>" <?php echo $is_active ? '' : 'hidden'; ?>>

                <header class="aiap-provider-panel-header">

                    <span class="aiap-provider-panel-icon ico ico-lg <?php echo esc_attr( $ii['ico'] ); ?>" aria-hidden="true"><?php echo esc_html( $ii['letter'] ); ?></span>

                    <span class="aiap-provider-panel-text">

                        <span class="aiap-provider-panel-title"><?php echo esc_html( $name ); ?></span>

                        <?php if ( $sub_text !== '' ) : ?>

                            <span class="aiap-provider-panel-sub"><?php echo esc_html( $sub_text ); ?></span>

                        <?php endif; ?>

                    </span>

                    <span class="aiap-provider-panel-active"><?php echo esc_html( __( 'In use', 'ai-auto-poster' ) ); ?></span>

                </header>

                <div class="aiap-provider-panel-body">

                    <?php if ( isset( $notes[ $card_key ] ) ) : ?>

                        <p class="aiap-field-note"><?php echo esc_html( AIAP_Admin_View::resolve_dynamic_key( $notes[ $card_key ] ) ); ?></p>

                    <?php endif; ?>



                    <?php if ( $ik ) : ?>

                        <div class="aiap-field">

                            <label class="aiap-field-label" for="aiap-img-apikey-<?php echo esc_attr( $card_key ); ?>"><?php echo esc_html( __( 'API Key', 'ai-auto-poster' ) ); ?></label>

                            <div class="aiap-field-row">

                                <?php
                                // $im は AIAP_Image_Client::get_settings() → get_decrypted() 経由で
                                // すでに復号済みの平文 API キーを保持している。再復号は不要。
                                AIAP_Admin_View::render_password_field( 'aiap-img-apikey-' . $card_key, $ik['key'], (string) ( $im[ $ik['key'] ] ?? '' ) );
                                ?>

                                <button type="button" class="aiap-btn aiap-btn-primary aiap-btn-test" data-test-kind="image" data-provider="<?php echo esc_attr( $card_key ); ?>">

                                    <span class="dashicons dashicons-search"></span> <?php echo esc_html( __( 'Test', 'ai-auto-poster' ) ); ?>

                                </button>

                            </div>

                            <div class="aiap-field-actions">

                                <a href="<?php echo esc_url( $ik['url'] ); ?>" target="_blank" rel="noopener" class="aiap-field-link">

                                    <?php echo esc_html( __( 'Get an API key', 'ai-auto-poster' ) ); ?>

                                    <svg viewBox="0 0 24 24" width="11" height="11" fill="none" aria-hidden="true"><path d="M7 17L17 7M17 7H9M17 7v8" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/></svg>

                                </a>

                            </div>

                        </div>

                        <?php if ( ! empty( $ik['models'] ) && ! empty( $ik['model'] ) ) : ?>

                            <div class="aiap-field">

                                <label class="aiap-field-label" for="aiap-img-model-<?php echo esc_attr( $card_key ); ?>"><?php echo esc_html( __( 'Model', 'ai-auto-poster' ) ); ?></label>

                                <select id="aiap-img-model-<?php echo esc_attr( $card_key ); ?>" name="<?php echo esc_attr( $ik['model'] ); ?>" class="aiap-select aiap-model-select" data-provider="<?php echo esc_attr( $card_key ); ?>">
                                    <?php foreach ( $ik['models'] as $m ) : ?>

                                        <option value="<?php echo esc_attr( $m ); ?>" <?php selected( $im[ $ik['model'] ] ?? '', $m ); ?>><?php echo esc_html( $m ); ?></option>

                                    <?php endforeach; ?>

                                </select>

                            </div>

                        <?php endif; ?>

                    <?php endif; ?>



                    <?php if ( in_array( $card_key, $dynamic_providers, true ) ) :

                        $mfield = $card_key . '_model';

                        $model_options = $img_models[ $card_key ] ?? array();

                        $cur_model = $im[ $mfield ] ?? '';

                        $custom_label = __( '(custom)', 'ai-auto-poster' );

                        if ( $cur_model !== '' && ! isset( $model_options[ $cur_model ] ) ) {

                            $model_options = array( $cur_model => $cur_model . ' ' . $custom_label ) + $model_options;

                        }

                        ?>

                        <div class="aiap-field">

                            <label class="aiap-field-label" for="aiap-img-dyn-model-<?php echo esc_attr( $card_key ); ?>"><?php echo esc_html( __( 'Model', 'ai-auto-poster' ) ); ?></label>

                            <div class="aiap-field-row">

                                <select id="aiap-img-dyn-model-<?php echo esc_attr( $card_key ); ?>" name="<?php echo esc_attr( $mfield ); ?>" class="aiap-select aiap-model-select" data-provider="<?php echo esc_attr( $card_key ); ?>">

                                    <?php foreach ( $model_options as $v => $l ) : ?>

                                        <option value="<?php echo esc_attr( $v ); ?>" <?php selected( $cur_model, $v ); ?>><?php echo esc_html( $l ); ?></option>

                                    <?php endforeach; ?>

                                </select>

                                <button type="button" class="aiap-btn aiap-btn-icon aiap-btn-refresh-models" data-provider="<?php echo esc_attr( $card_key ); ?>" title="<?php echo esc_attr( __( 'Refresh model list', 'ai-auto-poster' ) ); ?>" aria-label="<?php echo esc_attr( __( 'Refresh model list', 'ai-auto-poster' ) ); ?>">

                                    <span class="dashicons dashicons-update" aria-hidden="true"></span>

                                </button>

                            </div>

                            <?php if ( isset( $img_discontinued[ $card_key ] ) ) : ?>

                                <p class="aiap-model-notice"><span class="dashicons dashicons-warning" aria-hidden="true"></span> <?php

                                    /* translators: %s = image model identifier that has been discontinued */

                                    echo esc_html( sprintf( __( 'Selected model "%s" is no longer available. It will be switched on save.', 'ai-auto-poster' ), $img_discontinued[ $card_key ] ) );

                                ?></p>

                            <?php endif; ?>

                            <p class="aiap-model-feedback" data-provider="<?php echo esc_attr( $card_key ); ?>" hidden></p>

                        </div>

                    <?php endif; ?>



                    <div class="aiap-style-wrapper" data-style-wrapper data-provider="<?php echo esc_attr( $card_key ); ?>" <?php echo $style_has_opts ? '' : 'hidden'; ?>>

                        <div class="aiap-field">

                            <label class="aiap-field-label" for="aiap-img-style-<?php echo esc_attr( $card_key ); ?>"><?php echo esc_html( __( 'Style', 'ai-auto-poster' ) ); ?></label>

                            <select id="aiap-img-style-<?php echo esc_attr( $card_key ); ?>" name="<?php echo esc_attr( $style_key ); ?>" class="aiap-select aiap-style-select" data-provider="<?php echo esc_attr( $card_key ); ?>">

                                <?php if ( $style_has_opts ) : foreach ( $style_opts as $sk => $sv ) :

                                    $label = ! empty( $sv['label_key'] ) ? AIAP_Admin_View::resolve_dynamic_key( $sv['label_key'] ) : ( $sv['label_ja'] ?? $sk );

                                    ?>

                                    <option value="<?php echo esc_attr( $sk ); ?>" <?php selected( $cur_style, $sk ); ?>><?php echo esc_html( ( ! empty( $sv['icon'] ) ? $sv['icon'] . ' ' : '' ) . $label ); ?></option>

                                <?php endforeach; endif; ?>

                            </select>

                            <?php if ( $style_unsupported ) : ?>

                                <p class="aiap-model-notice" data-style-notice><span class="dashicons dashicons-warning" aria-hidden="true"></span>

                                    <?php

                                    /* translators: %s = style name not supported by the current model */

                                    echo esc_html( sprintf( __( 'Selected style "%s" is not supported by the current model. It will be reset to default on save.', 'ai-auto-poster' ), $style_unsupported ) );

                                    ?>

                                </p>

                            <?php else : ?>

                                <p class="aiap-model-notice" data-style-notice hidden><span class="dashicons dashicons-warning" aria-hidden="true"></span><span data-style-notice-text></span></p>

                            <?php endif; ?>

                            <span class="aiap-field-hint"><?php echo esc_html( __( 'Set the style for AI image generation.', 'ai-auto-poster' ) ); ?></span>

                        </div>

                    </div>

                </div>

            </div>

        <?php endforeach; ?>



        <p class="submit aiap-provider-submit"><button type="submit" class="button button-primary aiap-btn-primary"><span class="dashicons dashicons-saved"></span> <?php echo esc_html( __( 'Save', 'ai-auto-poster' ) ); ?></button></p>

        </form>

        <?php

    }



    /**

     * 画像プロバイダのサブタイトル

     */

    private static function image_provider_subtitle( $key ) {

        switch ( $key ) {

            case 'dalle3':    return __( 'OpenAI DALL-E', 'ai-auto-poster' );

            case 'imagen':    return __( 'Google Imagen', 'ai-auto-poster' );

            case 'stability': return __( 'Stable Diffusion', 'ai-auto-poster' );

            case 'flux':      return __( 'Black Forest Labs', 'ai-auto-poster' );

            case 'unsplash':  return __( 'Free stock photos', 'ai-auto-poster' );

            case 'pixabay':   return __( 'Free stock photos & videos', 'ai-auto-poster' );

            case 'pexels':    return __( 'Free stock photos', 'ai-auto-poster' );

            case 'openverse': return __( 'CC-licensed media', 'ai-auto-poster' );

        }

        return '';

    }



    // ================================================================

    // 画像設定 (BotWriter style — 2 column layout)

    // ================================================================

    public static function render_image_settings( $im ) {

        $cur_format  = $im['image_format']    ?? '16:9';

        $cur_quality = $im['image_quality']   ?? 'low';

        $cur_max     = (int) ( $im['image_max_width'] ?? 1200 );

        $cur_comp    = (int) ( $im['image_compress']  ?? 85 );



        $presets = self::get_image_presets();

        $current_preset = 'custom';

        foreach ( $presets as $key => $p ) {

            if ( $p['format'] === $cur_format

                && $p['quality'] === $cur_quality

                && $p['max_width'] === $cur_max

                && $p['compress'] === $cur_comp ) {

                $current_preset = $key;

                break;

            }

        }

        $current_label = ( 'custom' === $current_preset )

            ? __( 'Custom', 'ai-auto-poster' )

            : $presets[ $current_preset ]['title'];

        ?>

        <form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>" class="aiap-imgset-form">

        <input type="hidden" name="action" value="aiap_save_image_settings">

        <?php wp_nonce_field( AIAP_Admin::NONCE ); ?>

        <input type="hidden" name="image_preset" id="aiap-image-preset" value="<?php echo esc_attr( $current_preset ); ?>">



        <div class="aiap-imgset">



            <header class="aiap-imgset-hero">

                <span class="aiap-imgset-eyebrow"><?php echo esc_html__( 'Image Settings', 'ai-auto-poster' ); ?></span>

                <h2 class="aiap-imgset-title"><?php echo esc_html__( 'What is this image for?', 'ai-auto-poster' ); ?></h2>

                <p class="aiap-imgset-lede"><?php echo esc_html__( 'Pick a use case and we will set the size, quality, and file weight for you.', 'ai-auto-poster' ); ?></p>

            </header>



            <div class="aiap-imgset-presets" role="radiogroup" aria-label="<?php echo esc_attr__( 'Image preset', 'ai-auto-poster' ); ?>">

                <?php foreach ( $presets as $key => $p ) : ?>

                    <button type="button"

                        class="aiap-imgset-card aiap-imgset-card--<?php echo esc_attr( $key ); ?> <?php echo $current_preset === $key ? 'is-selected' : ''; ?>"

                        data-aiap-preset="<?php echo esc_attr( $key ); ?>"

                        data-aiap-format="<?php echo esc_attr( $p['format'] ); ?>"

                        data-aiap-quality="<?php echo esc_attr( $p['quality'] ); ?>"

                        data-aiap-max-width="<?php echo esc_attr( $p['max_width'] ); ?>"

                        data-aiap-compress="<?php echo esc_attr( $p['compress'] ); ?>"

                        role="radio"

                        aria-checked="<?php echo $current_preset === $key ? 'true' : 'false'; ?>">

                        <span class="aiap-imgset-card__visual" aria-hidden="true">

                            <?php echo self::get_preset_icon_svg( $key ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- hardcoded SVG ?>

                        </span>

                        <span class="aiap-imgset-card__body">

                            <span class="aiap-imgset-card__title">

                                <span class="aiap-imgset-card__name"><?php echo esc_html( $p['title'] ); ?></span>

                                <span class="aiap-imgset-card__check" aria-hidden="true">

                                    <svg viewBox="0 0 24 24" width="14" height="14" fill="none"><path d="M5 12l5 5L20 7" stroke="currentColor" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/></svg>

                                    <?php echo esc_html__( 'Selected', 'ai-auto-poster' ); ?>

                                </span>

                            </span>

                            <span class="aiap-imgset-card__sub"><?php echo esc_html( $p['description'] ); ?></span>

                            <span class="aiap-imgset-card__chips">

                                <?php foreach ( $p['chips'] as $chip ) : ?>

                                    <span class="aiap-imgset-card__chip"><?php echo esc_html( $chip ); ?></span>

                                <?php endforeach; ?>

                            </span>

                        </span>

                    </button>

                <?php endforeach; ?>

            </div>



            <div class="aiap-imgset-current">

                <span class="aiap-imgset-current__dot" aria-hidden="true"></span>

                <span class="aiap-imgset-current__text">

                    <strong id="aiap-current-preset-label" data-custom-label="<?php echo esc_attr__( 'Custom', 'ai-auto-poster' ); ?>"><?php echo esc_html( $current_label ); ?></strong>

                    <?php echo esc_html__( 'will be used to generate images', 'ai-auto-poster' ); ?>

                </span>

            </div>



            <div class="aiap-imgset-advanced <?php echo $current_preset === 'custom' ? 'is-open' : ''; ?>" id="aiap-imgset-advanced">

                <button type="button" class="aiap-imgset-advanced__toggle" id="aiap-imgset-advanced-toggle" aria-expanded="<?php echo $current_preset === 'custom' ? 'true' : 'false'; ?>" aria-controls="aiap-imgset-advanced-panel">

                    <span class="aiap-imgset-advanced__label">

                        <span class="aiap-imgset-advanced__label-main"><?php echo esc_html__( 'Advanced settings', 'ai-auto-poster' ); ?></span>

                        <span class="aiap-imgset-advanced__caption"><?php echo esc_html__( 'For users who want to set size and quality manually', 'ai-auto-poster' ); ?></span>

                    </span>

                    <svg class="aiap-imgset-advanced__chev" width="18" height="18" viewBox="0 0 24 24" fill="none" aria-hidden="true">

                        <path d="M6 9l6 6 6-6" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round"/>

                    </svg>

                </button>



                <div class="aiap-imgset-advanced__panel" id="aiap-imgset-advanced-panel">

                    <div class="aiap-imgset-field">

                        <label for="aiap-image-format"><?php echo esc_html__( 'Image shape', 'ai-auto-poster' ); ?></label>

                        <select name="image_format" id="aiap-image-format" class="aiap-full-select">

                            <?php foreach ( AIAP_Admin::$image_format_keys as $k ) : ?>

                                <option value="<?php echo esc_attr( $k ); ?>" <?php selected( $cur_format, $k ); ?>>

                                    <?php echo esc_html( AIAP_Admin_View::resolve_dynamic_key( 'imgfmt_' . str_replace( ':', '_', $k ) ) ); ?>

                                </option>

                            <?php endforeach; ?>

                        </select>

                    </div>



                    <div class="aiap-imgset-field">

                        <label for="aiap-image-quality"><?php echo esc_html__( 'Image quality', 'ai-auto-poster' ); ?></label>

                        <select name="image_quality" id="aiap-image-quality" class="aiap-full-select">

                            <?php foreach ( AIAP_Admin::$image_quality_keys as $k ) : ?>

                                <option value="<?php echo esc_attr( $k ); ?>" <?php selected( $cur_quality, $k ); ?>>

                                    <?php echo esc_html( AIAP_Admin_View::resolve_dynamic_key( 'imgqual_' . $k ) ); ?>

                                </option>

                            <?php endforeach; ?>

                        </select>

                    </div>



                    <div class="aiap-imgset-field">

                        <label for="aiap-image-max-width"><?php echo esc_html__( 'Image size', 'ai-auto-poster' ); ?></label>

                        <div class="aiap-imgset-field__row">

                            <input type="number" name="image_max_width" id="aiap-image-max-width"

                                value="<?php echo esc_attr( $cur_max ); ?>" min="100" max="4096">

                            <span class="aiap-imgset-field__unit">px</span>

                        </div>

                        <span class="aiap-imgset-field__hint"><?php echo esc_html__( 'Recommended: Blog 1200px / SNS 1080px / Lite 800px', 'ai-auto-poster' ); ?></span>

                    </div>



                    <div class="aiap-imgset-field">

                        <label for="aiap-image-compress"><?php echo esc_html__( 'File weight (compression quality)', 'ai-auto-poster' ); ?></label>

                        <div class="aiap-imgset-field__row">

                            <input type="number" name="image_compress" id="aiap-image-compress"

                                value="<?php echo esc_attr( $cur_comp ); ?>" min="1" max="100">

                            <span class="aiap-imgset-field__unit">%</span>

                        </div>

                        <span class="aiap-imgset-field__hint"><?php echo esc_html__( 'Higher = better looking, lower = lighter file. Standard is 85%.', 'ai-auto-poster' ); ?></span>

                    </div>



                    <p class="aiap-imgset-field__note"><?php

                        /* Phase 12: 旧版は単に「in the SEO section」と書くだけで、ユーザーは

                           どのタブのどこにあるか分からなかった。基本設定タブの SEO アコーディオンへの

                           直接リンクに変更し、クリック 1 回で該当箇所まで飛べるようにする。

                           open=seo クエリパラメータと #aiap-seo-section ハッシュを併用し、

                           render_settings 側でアコーディオンを自動展開する。 */

                        $seo_url = add_query_arg(

                            array(

                                'page' => AIAP_Admin::MENU_SLUG,

                                'tab'  => 'settings',

                                'open' => 'seo',

                            ),

                            admin_url( 'admin.php' )

                        ) . '#aiap-seo-section';

                        printf(

                            /* translators: %s = HTML link to "WebP conversion and compression" setting in SEO section */

                            esc_html__( 'Size and compression apply only when %s is enabled.', 'ai-auto-poster' ),

                            '<a href="' . esc_url( $seo_url ) . '">' . esc_html__( '"WebP conversion and compression" in the SEO section', 'ai-auto-poster' ) . '</a>'

                        );

                    ?></p>

                </div>

            </div>



            <p class="submit aiap-imgset-submit">

                <button type="submit" class="button button-primary aiap-btn-primary">

                    <span class="dashicons dashicons-saved"></span>

                    <?php echo esc_html__( 'Save Image Settings', 'ai-auto-poster' ); ?>

                </button>

            </p>



        </div>

        </form>

        <?php

    }



    /**

     * 画像設定プリセット定義。

     */

    private static function get_image_presets() {

        return array(

            'blog' => array(

                'title'       => __( 'Blog post', 'ai-auto-poster' ),

                'description' => __( 'For headers and inline article images. Balanced quality.', 'ai-auto-poster' ),

                'chips'       => array(

                    __( 'Landscape', 'ai-auto-poster' ),

                    __( 'Balanced', 'ai-auto-poster' ),

                    __( 'Standard size', 'ai-auto-poster' ),

                ),

                'format'      => '16:9',

                'quality'     => 'medium',

                'max_width'   => 1200,

                'compress'    => 85,

            ),

            'sns' => array(

                'title'       => __( 'Social media', 'ai-auto-poster' ),

                'description' => __( 'Square format that shares well on Instagram and X.', 'ai-auto-poster' ),

                'chips'       => array(

                    __( 'Square', 'ai-auto-poster' ),

                    __( 'Balanced', 'ai-auto-poster' ),

                    __( 'Compatible', 'ai-auto-poster' ),

                ),

                'format'      => '1:1',

                'quality'     => 'medium',

                'max_width'   => 1080,

                'compress'    => 80,

            ),

            'lite' => array(

                'title'       => __( 'Lightweight', 'ai-auto-poster' ),

                'description' => __( 'Site loads faster. Quality is slightly lower.', 'ai-auto-poster' ),

                'chips'       => array(

                    __( 'Smaller', 'ai-auto-poster' ),

                    __( 'Speed first', 'ai-auto-poster' ),

                    __( 'Saves data', 'ai-auto-poster' ),

                ),

                'format'      => '16:9',

                'quality'     => 'low',

                'max_width'   => 800,

                'compress'    => 70,

            ),

        );

    }



    /**

     * 装飾用 SVG (ハードコード、ユーザー入力を含まない)

     */

    private static function get_preset_icon_svg( $preset ) {

        switch ( $preset ) {

            case 'blog':

                return '<svg viewBox="0 0 64 64" width="56" height="56" fill="none" focusable="false"><rect x="6" y="14" width="52" height="36" rx="3" fill="#fff" stroke="#c2410c" stroke-width="2"/><line x1="12" y1="24" x2="40" y2="24" stroke="#c2410c" stroke-width="2.5" stroke-linecap="round"/><line x1="12" y1="32" x2="52" y2="32" stroke="#c2410c" stroke-width="2" stroke-linecap="round" opacity=".5"/><line x1="12" y1="38" x2="48" y2="38" stroke="#c2410c" stroke-width="2" stroke-linecap="round" opacity=".5"/><line x1="12" y1="44" x2="44" y2="44" stroke="#c2410c" stroke-width="2" stroke-linecap="round" opacity=".5"/></svg>';

            case 'sns':

                return '<svg viewBox="0 0 64 64" width="56" height="56" fill="none" focusable="false"><rect x="14" y="14" width="36" height="36" rx="3" fill="#fff" stroke="#047857" stroke-width="2"/><circle cx="42" cy="22" r="2.5" fill="#047857"/><path d="M14 42 L24 32 L34 40 L42 34 L50 42" stroke="#047857" stroke-width="2" fill="none" stroke-linecap="round" stroke-linejoin="round"/><path d="M14 50 L50 50" stroke="#047857" stroke-width="2" stroke-linecap="round"/></svg>';

            case 'lite':

                return '<svg viewBox="0 0 64 64" width="56" height="56" fill="none" focusable="false"><path d="M28 8 L18 36 L30 36 L24 56 L46 28 L34 28 L40 8 Z" fill="#fff" stroke="#3730a3" stroke-width="2" stroke-linejoin="round"/></svg>';

        }

        return '';

    }



    // ================================================================

    // プロンプト管理 (unchanged)

}

