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

/**
 * AIモデルの定期同期 (Phase 1: プロバイダ API ベース)
 *
 * 動作:
 *  - 週次 cron で API キーが保存されている各プロバイダの /models を取得
 *  - 取得結果は AIAP_AI_Client の transient キャッシュ (24h) に保存
 *  - 保存中のモデルが取得結果に含まれていなければ "discontinued" として記録
 *  - 管理画面で記録された discontinued をユーザーに警告 (admin_notices)
 *
 * 設計方針:
 *  - 外部インフラ非依存 (既存の AI API のみを利用)
 *  - API エラー時は黙ってスキップ (次回 cron でリトライ)。"discontinued" 判定は
 *    取得が成功した場合に限るため、一時的なネットワーク障害で誤検知しない
 *  - cron 経路のみで動作。フロント/管理画面の通常リクエストでは API を叩かない
 */
class AIAP_Model_Sync {

    const CRON_HOOK   = 'aiap_model_sync';
    const STATUS_OPT  = 'aiap_model_sync_status';
    const SCHEDULE    = 'weekly';
    // wp_remote_get タイムアウト (バックグラウンド処理なので長めに)
    const FETCH_TIMEOUT = 15;

    /**
     * フックを登録する (plugins_loaded から呼ばれる)
     */
    public static function init() {
        add_action( self::CRON_HOOK, array( __CLASS__, 'run_sync' ) );
        // セーフティネット: cron 登録が消えたら admin 経路で再登録 (Scheduler と同パターン)
        add_action( 'admin_init', array( __CLASS__, 'ensure_scheduled' ) );
    }

    /**
     * cron 未登録なら登録する。WP 既定の 'weekly' を使う。
     */
    public static function ensure_scheduled() {
        if ( ! wp_next_scheduled( self::CRON_HOOK ) ) {
            // 既存の AIAP_CRON_HOOK (5分間隔の本処理) と干渉しないように、初回は1時間後にずらす。
            wp_schedule_event( time() + HOUR_IN_SECONDS, self::SCHEDULE, self::CRON_HOOK );
        }
    }

    /**
     * プラグイン有効化時のフック登録
     */
    public static function activate() {
        self::ensure_scheduled();
    }

    /**
     * プラグイン無効化時のフック解除 + 状態クリア
     */
    public static function deactivate() {
        wp_clear_scheduled_hook( self::CRON_HOOK );
        // 状態 option は残す (再有効化時に直近の警告状態を保持するため)。
        // 完全な削除は aiap_uninstall_cleanup_site() (ai-auto-poster.php) で実施。
    }

    /**
     * 同期実行 (cron から呼ばれる)
     *
     * 各プロバイダの /models を取得し、transient と discontinued ステータスを更新する。
     */
    public static function run_sync() {
        if ( ! class_exists( 'AIAP_AI_Client' ) ) {
            return;
        }

        $settings = AIAP_AI_Client::get_settings();
        if ( ! is_array( $settings ) ) {
            return;
        }

        $status = get_option( self::STATUS_OPT, array() );
        if ( ! is_array( $status ) ) {
            $status = array();
        }

        // テキストプロバイダ + 画像プロバイダのうち、モデル選択 UI を持つもの
        // (dalle3 / imagen は API キーが image-client 側に保存されているため別途処理)
        $text_providers = AIAP_AI_Providers::get_providers();

        foreach ( $text_providers as $provider ) {
            self::sync_text_provider( $provider, $settings, $status );
        }

        // 画像プロバイダ (dalle3 / imagen は AIAP_Image_Client::get_settings() の API キーを使う)
        if ( class_exists( 'AIAP_Image_Client' ) ) {
            $image_settings = AIAP_Image_Client::get_settings();
            if ( is_array( $image_settings ) ) {
                self::sync_image_provider( 'dalle3', $image_settings, $status );
                self::sync_image_provider( 'imagen', $image_settings, $status );
            }
        }

        update_option( self::STATUS_OPT, $status, false );
    }

    /**
     * テキストプロバイダ 1 つを同期する
     */
    private static function sync_text_provider( $provider, $settings, &$status ) {
        $key_field   = $provider . '_api_key';
        $model_field = $provider . '_model';
        $api_key     = isset( $settings[ $key_field ] ) ? (string) $settings[ $key_field ] : '';
        $saved_model = isset( $settings[ $model_field ] ) ? (string) $settings[ $model_field ] : '';

        // API キー未設定なら同期不能 (黙ってスキップ)
        if ( $api_key === '' ) {
            // 既存ステータスはそのまま残す (キー削除で discontinued 警告が即消える挙動を避ける)。
            // ただし long-stale なら自動クリアする選択肢もあるが、Phase 1 では単純化のため保持。
            return;
        }

        // /models 取得 (AIAP_AI_Client 内部で wp_remote_get を使う)
        $models = AIAP_AI_Providers::fetch_models_from_api( $provider );
        if ( is_wp_error( $models ) || ! is_array( $models ) || empty( $models ) ) {
            // 取得失敗時は何もしない (誤検知防止)。次回 cron でリトライ。
            return;
        }

        // 取得成功 → transient キャッシュを更新
        AIAP_AI_Providers::cache_models( $provider, $models );

        // discontinued 判定
        $entry = array(
            'last_check'         => time(),
            'discontinued_model' => null,
        );
        if ( $saved_model !== '' && ! isset( $models[ $saved_model ] ) ) {
            $entry['discontinued_model'] = $saved_model;
        }
        $status[ $provider ] = $entry;
    }

    /**
     * 画像プロバイダ 1 つを同期する (dalle3 / imagen)
     */
    private static function sync_image_provider( $provider, $image_settings, &$status ) {
        // 画像プロバイダの API キー保存先は image-client の image_*_api_key 系
        $key_fields = array(
            'dalle3' => 'image_openai_api_key',
            'imagen' => 'image_gemini_api_key',
        );
        if ( ! isset( $key_fields[ $provider ] ) ) {
            return;
        }
        $api_key     = isset( $image_settings[ $key_fields[ $provider ] ] ) ? (string) $image_settings[ $key_fields[ $provider ] ] : '';
        $model_field = $provider . '_model';
        $saved_model = isset( $image_settings[ $model_field ] ) ? (string) $image_settings[ $model_field ] : '';

        if ( $api_key === '' ) {
            return;
        }

        $models = AIAP_AI_Providers::fetch_models_from_api( $provider );
        if ( is_wp_error( $models ) || ! is_array( $models ) || empty( $models ) ) {
            return;
        }

        AIAP_AI_Providers::cache_models( $provider, $models );

        $entry = array(
            'last_check'         => time(),
            'discontinued_model' => null,
        );
        if ( $saved_model !== '' && ! isset( $models[ $saved_model ] ) ) {
            $entry['discontinued_model'] = $saved_model;
        }
        $status[ $provider ] = $entry;
    }

    /**
     * 管理画面で警告すべき discontinued エントリを返す
     *
     * @return array provider => discontinued_model (string)
     */
    public static function get_discontinued() {
        $status = get_option( self::STATUS_OPT, array() );
        if ( ! is_array( $status ) ) {
            return array();
        }
        $out = array();
        foreach ( $status as $provider => $entry ) {
            if ( ! is_array( $entry ) ) {
                continue;
            }
            $model = isset( $entry['discontinued_model'] ) ? (string) $entry['discontinued_model'] : '';
            if ( $model !== '' ) {
                $out[ $provider ] = $model;
            }
        }
        return $out;
    }
}
